Merge remote-tracking branch 'upstream/develop' into xap
This commit is contained in:
commit
dcf4bf6d29
8302 changed files with 152923 additions and 60301 deletions
|
|
@ -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"
|
||||
|
|
@ -634,12 +633,7 @@ void process_action(keyrecord_t *record, action_t action) {
|
|||
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) {
|
||||
|
|
@ -712,11 +706,6 @@ void process_action(keyrecord_t *record, action_t action) {
|
|||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_ACTION_FUNCTION
|
||||
case ACT_FUNCTION:
|
||||
action_function(record, action.func.id, action.func.opt);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
|
@ -794,7 +783,7 @@ void process_action(keyrecord_t *record, action_t action) {
|
|||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void register_code(uint8_t code) {
|
||||
__attribute__((weak)) void register_code(uint8_t code) {
|
||||
if (code == KC_NO) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -890,7 +879,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;
|
||||
}
|
||||
|
|
@ -955,7 +944,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);
|
||||
|
|
@ -967,13 +956,13 @@ 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_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
|
||||
__attribute__((weak)) void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : 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();
|
||||
|
|
@ -984,7 +973,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();
|
||||
|
|
@ -995,7 +984,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();
|
||||
|
|
@ -1006,7 +995,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();
|
||||
|
|
@ -1041,7 +1030,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();
|
||||
|
|
@ -1104,12 +1092,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;
|
||||
}
|
||||
|
|
@ -1166,12 +1148,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -21,12 +21,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "action_layer.h"
|
||||
#include "timer.h"
|
||||
#include "keycode_config.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;
|
||||
|
|
@ -223,7 +223,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) {
|
||||
|
|
@ -247,7 +246,13 @@ void send_keyboard_report(void) {
|
|||
keyboard_report->mods |= weak_override_mods;
|
||||
#endif
|
||||
|
||||
host_keyboard_send(keyboard_report);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Get mods
|
||||
|
|
@ -318,33 +323,6 @@ void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; }
|
|||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -49,13 +49,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);
|
||||
|
|
|
|||
|
|
@ -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,6 +174,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -232,19 +232,19 @@ ISR(TIMERx_OVF_vect) {
|
|||
|
||||
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||
static uint16_t cie_lightness(uint16_t v) {
|
||||
if (v <= 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%
|
||||
} 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 + ICRx / 6) << 5) / (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
|
||||
{
|
||||
out = ICRx;
|
||||
}
|
||||
return out;
|
||||
return (uint16_t)out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,8 +44,6 @@ 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.
|
||||
# include "none.c"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
72
quantum/debounce/sym_defer_pr.c
Normal file
72
quantum/debounce/sym_defer_pr.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
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; }
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,15 @@ 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);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "keymap.h" // to get keymaps[][][]
|
||||
#include "eeprom.h"
|
||||
#include "progmem.h" // to read default from flash
|
||||
|
|
@ -30,24 +29,22 @@
|
|||
# define DYNAMIC_KEYMAP_MACRO_COUNT 16
|
||||
#endif
|
||||
|
||||
// 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 TOTAL_EEPROM_BYTE_COUNT
|
||||
# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps.
|
||||
#endif
|
||||
|
||||
#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
|
||||
# else
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
|
||||
# endif
|
||||
# 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
|
||||
|
||||
|
|
@ -72,6 +69,7 @@
|
|||
// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
|
||||
// more than the default.
|
||||
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR < 100
|
||||
# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) " < 100"
|
||||
# error Dynamic keymaps are configured to use more EEPROM than is available.
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -100,6 +102,12 @@ 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; }
|
||||
|
|
@ -290,6 +298,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
|
||||
|
|
@ -299,8 +337,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
|
||||
|
|
@ -341,6 +383,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;
|
||||
|
|
@ -363,28 +408,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();
|
||||
|
|
@ -431,10 +465,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
|
||||
|
|
@ -453,7 +571,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
|
||||
|
||||
|
|
@ -516,22 +634,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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
@ -80,24 +79,6 @@ action_t action_for_keycode(uint16_t keycode) {
|
|||
// Split it up
|
||||
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) // %
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
@ -135,3 +140,41 @@ __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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -27,6 +28,9 @@
|
|||
#ifdef IS31FL3731
|
||||
# include "is31fl3731-simple.h"
|
||||
#endif
|
||||
#ifdef IS31FL3733
|
||||
# include "is31fl3733-simple.h"
|
||||
#endif
|
||||
|
||||
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
|
||||
# define LED_MATRIX_LED_FLUSH_LIMIT 16
|
||||
|
|
|
|||
|
|
@ -63,17 +63,13 @@ 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 {
|
||||
|
|
@ -256,8 +252,6 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[]
|
|||
|
||||
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
|
||||
|
|
@ -296,10 +290,6 @@ void matrix_init(void) {
|
|||
debounce_init(ROWS_PER_HAND);
|
||||
|
||||
matrix_init_quantum();
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_post_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
|
|
@ -308,35 +298,6 @@ __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_mat
|
|||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t matrix_scan(void) {
|
||||
|
|
|
|||
|
|
@ -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,6 +22,11 @@
|
|||
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
|
||||
|
|
@ -45,12 +59,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 +92,57 @@ uint8_t matrix_key_count(void) {
|
|||
return count;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
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; }
|
||||
|
||||
#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 +151,7 @@ __attribute__((weak)) void matrix_init(void) {
|
|||
matrix[i] = 0;
|
||||
}
|
||||
|
||||
debounce_init(MATRIX_ROWS);
|
||||
debounce_init(ROWS_PER_HAND);
|
||||
|
||||
matrix_init_quantum();
|
||||
}
|
||||
|
|
@ -112,9 +159,14 @@ __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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,105 @@
|
|||
|
||||
#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;
|
||||
|
||||
/**
|
||||
* @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) {}
|
||||
/**
|
||||
* @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 +126,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 +145,295 @@ __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)
|
||||
|
|
|
|||
|
|
@ -165,14 +165,13 @@ const pointing_device_driver_t pointing_device_driver = {
|
|||
// clang-format on
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
|
||||
report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
|
||||
static fast_timer_t throttle = 0;
|
||||
static uint16_t debounce = 0;
|
||||
static uint8_t error_count = 0;
|
||||
pimoroni_data_t pimoroni_data = {0};
|
||||
static int16_t x_offset = 0, y_offset = 0;
|
||||
report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
|
||||
static uint16_t debounce = 0;
|
||||
static uint8_t error_count = 0;
|
||||
pimoroni_data_t pimoroni_data = {0};
|
||||
static int16_t x_offset = 0, y_offset = 0;
|
||||
|
||||
if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
|
||||
if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
|
||||
i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
|
||||
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
|
|
@ -195,22 +194,20 @@ report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
|
|||
} else {
|
||||
error_count++;
|
||||
}
|
||||
throttle = timer_read_fast();
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = pimironi_trackball_device_init,
|
||||
.get_report = pimorono_trackball_get_report,
|
||||
.set_cpi = NULL,
|
||||
.get_cpi = NULL
|
||||
.init = pimoroni_trackball_device_init,
|
||||
.get_report = pimoroni_trackball_get_report,
|
||||
.set_cpi = pimoroni_trackball_set_cpi,
|
||||
.get_cpi = pimoroni_trackball_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
|
||||
|
||||
static void init(void) { pmw3360_init(); }
|
||||
static void pmw3360_device_init(void) { pmw3360_init(); }
|
||||
|
||||
report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
|
||||
report_pmw3360_t data = pmw3360_read_burst();
|
||||
|
|
@ -239,12 +236,48 @@ report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
|
|||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = init,
|
||||
.init = pmw3360_device_init,
|
||||
.get_report = pmw3360_get_report,
|
||||
.set_cpi = pmw3360_set_cpi,
|
||||
.get_cpi = pmw3360_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3389)
|
||||
static void pmw3389_device_init(void) { pmw3389_init(); }
|
||||
|
||||
report_mouse_t pmw3389_get_report(report_mouse_t mouse_report) {
|
||||
report_pmw3389_t data = pmw3389_read_burst();
|
||||
static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
|
||||
|
||||
if (data.isOnSurface && data.isMotion) {
|
||||
// Reset timer if stopped moving
|
||||
if (!data.isMotion) {
|
||||
if (MotionStart != 0) MotionStart = 0;
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// Set timer if new motion
|
||||
if ((MotionStart == 0) && data.isMotion) {
|
||||
# ifdef CONSOLE_ENABLE
|
||||
if (debug_mouse) dprintf("Starting motion.\n");
|
||||
# endif
|
||||
MotionStart = timer_read();
|
||||
}
|
||||
mouse_report.x = constrain_hid(data.dx);
|
||||
mouse_report.y = constrain_hid(data.dy);
|
||||
}
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = pmw3389_device_init,
|
||||
.get_report = pmw3389_get_report,
|
||||
.set_cpi = pmw3389_set_cpi,
|
||||
.get_cpi = pmw3389_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
#else
|
||||
__attribute__((weak)) void pointing_device_driver_init(void) {}
|
||||
__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; }
|
||||
|
|
|
|||
|
|
@ -57,3 +57,4 @@ void process_audio_noteoff(uint8_t note) { stop_note(compute_freq_for_midi_note(
|
|||
void process_audio_all_notes_off(void) { stop_all_notes(); }
|
||||
|
||||
__attribute__((weak)) void audio_on_user() {}
|
||||
__attribute__((weak)) void audio_off_user() {}
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ void process_audio_noteoff(uint8_t note);
|
|||
void process_audio_all_notes_off(void);
|
||||
|
||||
void audio_on_user(void);
|
||||
void audio_off_user(void);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "print.h"
|
||||
#include "process_combo.h"
|
||||
#include "action_tapping.h"
|
||||
#include "action.h"
|
||||
|
||||
#ifdef COMBO_COUNT
|
||||
__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
|
||||
|
|
@ -40,10 +41,18 @@ __attribute__((weak)) bool get_combo_must_tap(uint16_t index, combo_t *combo) {
|
|||
__attribute__((weak)) uint16_t get_combo_term(uint16_t index, combo_t *combo) { return COMBO_TERM; }
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_MUST_PRESS_IN_ORDER_PER_COMBO
|
||||
__attribute__((weak)) bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) { return true; }
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_PROCESS_KEY_RELEASE
|
||||
__attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode) { return false; }
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_SHOULD_TRIGGER
|
||||
__attribute__((weak)) bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record) { return true; }
|
||||
#endif
|
||||
|
||||
#ifndef COMBO_NO_TIMER
|
||||
static uint16_t timer = 0;
|
||||
#endif
|
||||
|
|
@ -185,6 +194,9 @@ void clear_combos(void) {
|
|||
static inline void dump_key_buffer(void) {
|
||||
/* First call start from 0 index; recursive calls need to start from i+1 index */
|
||||
static uint8_t key_buffer_next = 0;
|
||||
#if TAP_CODE_DELAY > 0
|
||||
bool delay_done = false;
|
||||
#endif
|
||||
|
||||
if (key_buffer_size == 0) {
|
||||
return;
|
||||
|
|
@ -210,6 +222,15 @@ static inline void dump_key_buffer(void) {
|
|||
#endif
|
||||
}
|
||||
record->event.time = 0;
|
||||
clear_weak_mods();
|
||||
|
||||
#if TAP_CODE_DELAY > 0
|
||||
// only delay once and for a non-tapping key
|
||||
if (!delay_done && !is_tap_record(record)) {
|
||||
delay_done = true;
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
key_buffer_next = key_buffer_size = 0;
|
||||
|
|
@ -350,6 +371,28 @@ combo_t *overlaps(combo_t *combo1, combo_t *combo2) {
|
|||
return combo1;
|
||||
}
|
||||
|
||||
#if defined(COMBO_MUST_PRESS_IN_ORDER) || defined(COMBO_MUST_PRESS_IN_ORDER_PER_COMBO)
|
||||
static bool keys_pressed_in_order(uint16_t combo_index, combo_t *combo, uint16_t key_index, uint16_t keycode, keyrecord_t *record) {
|
||||
# ifdef COMBO_MUST_PRESS_IN_ORDER_PER_COMBO
|
||||
if (!get_combo_must_press_in_order(combo_index, combo)) {
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
if (
|
||||
// The `state` bit for the key being pressed.
|
||||
(1 << key_index) ==
|
||||
// The *next* combo key's bit.
|
||||
(COMBO_STATE(combo) + 1)
|
||||
// E.g. two keys already pressed: `state == 11`.
|
||||
// Next possible `state` is `111`.
|
||||
// So the needed bit is `100` which we get with `11 + 1`.
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {
|
||||
uint8_t key_count = 0;
|
||||
uint16_t key_index = -1;
|
||||
|
|
@ -360,7 +403,14 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
|
|||
return false;
|
||||
}
|
||||
|
||||
bool key_is_part_of_combo = !COMBO_DISABLED(combo) && is_combo_enabled();
|
||||
bool key_is_part_of_combo = (!COMBO_DISABLED(combo) && is_combo_enabled()
|
||||
#if defined(COMBO_MUST_PRESS_IN_ORDER) || defined(COMBO_MUST_PRESS_IN_ORDER_PER_COMBO)
|
||||
&& keys_pressed_in_order(combo_index, combo, key_index, keycode, record)
|
||||
#endif
|
||||
#ifdef COMBO_SHOULD_TRIGGER
|
||||
&& combo_should_trigger(combo_index, combo, keycode, record)
|
||||
#endif
|
||||
);
|
||||
|
||||
if (record->event.pressed && key_is_part_of_combo) {
|
||||
uint16_t time = _get_combo_term(combo_index, combo);
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
*/
|
||||
#include "process_grave_esc.h"
|
||||
|
||||
/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
|
||||
/* true if the last press of QK_GRAVE_ESCAPE was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
|
||||
* Used to ensure that the correct keycode is released if the key is released.
|
||||
*/
|
||||
static bool grave_esc_was_shifted = false;
|
||||
|
||||
bool process_grave_esc(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == GRAVE_ESC) {
|
||||
if (keycode == QK_GRAVE_ESCAPE) {
|
||||
const uint8_t mods = get_mods();
|
||||
uint8_t shifted = mods & MOD_MASK_SG;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
|
|||
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
|
||||
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
|
||||
#endif
|
||||
#ifdef NO_HAPTIC_FN
|
||||
case KC_FN0 ... KC_FN31:
|
||||
#endif
|
||||
#ifdef NO_HAPTIC_ALPHA
|
||||
case KC_A ... KC_Z:
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,10 +28,11 @@ bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) {
|
|||
if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX) {
|
||||
return true;
|
||||
} else {
|
||||
uint8_t button_idx = (keycode - JS_BUTTON0);
|
||||
if (record->event.pressed) {
|
||||
joystick_status.buttons[(keycode - JS_BUTTON0) / 8] |= 1 << (keycode % 8);
|
||||
joystick_status.buttons[button_idx / 8] |= 1 << (button_idx % 8);
|
||||
} else {
|
||||
joystick_status.buttons[(keycode - JS_BUTTON0) / 8] &= ~(1 << (keycode % 8));
|
||||
joystick_status.buttons[button_idx / 8] &= ~(1 << (button_idx % 8));
|
||||
}
|
||||
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ static inline uint16_t translate_keycode(uint16_t keycode) {
|
|||
}
|
||||
}
|
||||
|
||||
void cancel_key_lock(void) {
|
||||
watching = false;
|
||||
UNSET_KEY_STATE(0x0);
|
||||
}
|
||||
|
||||
bool process_key_lock(uint16_t *keycode, keyrecord_t *record) {
|
||||
// We start by categorizing the keypress event. In the event of a down
|
||||
// event, there are several possibilities:
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@
|
|||
|
||||
#include "quantum.h"
|
||||
|
||||
void cancel_key_lock(void);
|
||||
bool process_key_lock(uint16_t *keycode, keyrecord_t *record);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
|||
case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI:
|
||||
case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT:
|
||||
case MAGIC_TOGGLE_GUI:
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
/* keymap config */
|
||||
keymap_config.raw = eeconfig_read_keymap();
|
||||
switch (keycode) {
|
||||
|
|
@ -168,6 +169,9 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
|||
case MAGIC_TOGGLE_GUI:
|
||||
keymap_config.no_gui = !keymap_config.no_gui;
|
||||
break;
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
|
||||
break;
|
||||
}
|
||||
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
#include "process_printer.h"
|
||||
#include "action_util.h"
|
||||
#include "uart.h"
|
||||
|
||||
bool printing_enabled = false;
|
||||
uint8_t character_shift = 0;
|
||||
|
||||
void enable_printing(void) {
|
||||
printing_enabled = true;
|
||||
serial_init();
|
||||
uart_init(19200);
|
||||
}
|
||||
|
||||
void disable_printing(void) { printing_enabled = false; }
|
||||
|
|
@ -35,7 +36,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
|
|||
|
||||
void print_char(char c) {
|
||||
USB_Disable();
|
||||
serial_send(c);
|
||||
uart_write(c);
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,4 @@
|
|||
|
||||
#include "quantum.h"
|
||||
|
||||
#include "protocol/serial.h"
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record);
|
||||
|
|
|
|||
|
|
@ -51,12 +51,8 @@ static void __attribute__((noinline, unused)) handleKeycodeRGBMode(const uint8_t
|
|||
* Handle keycodes for both rgblight and rgbmatrix
|
||||
*/
|
||||
bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
|
||||
#ifndef SPLIT_KEYBOARD
|
||||
if (record->event.pressed) {
|
||||
#else
|
||||
// Split keyboards need to trigger on key-up for edge-case issue
|
||||
// need to trigger on key-up for edge-case issue
|
||||
if (!record->event.pressed) {
|
||||
#endif
|
||||
#if (defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)) || (defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES))
|
||||
uint8_t shifted = get_mods() & MOD_MASK_SHIFT;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "magic.h"
|
||||
|
||||
#ifdef BLUETOOTH_ENABLE
|
||||
# include "outputselect.h"
|
||||
|
|
@ -47,10 +46,6 @@ float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef AUTO_SHIFT_ENABLE
|
||||
# include "process_auto_shift.h"
|
||||
#endif
|
||||
|
||||
uint8_t extract_mod_bits(uint16_t code) {
|
||||
switch (code) {
|
||||
case QK_MODS ... QK_MODS_MAX:
|
||||
|
|
@ -76,9 +71,9 @@ uint8_t extract_mod_bits(uint16_t code) {
|
|||
return mods_to_send;
|
||||
}
|
||||
|
||||
static void do_code16(uint16_t code, void (*f)(uint8_t)) { f(extract_mod_bits(code)); }
|
||||
void do_code16(uint16_t code, void (*f)(uint8_t)) { f(extract_mod_bits(code)); }
|
||||
|
||||
void register_code16(uint16_t code) {
|
||||
__attribute__((weak)) void register_code16(uint16_t code) {
|
||||
if (IS_MOD(code) || code == KC_NO) {
|
||||
do_code16(code, register_mods);
|
||||
} else {
|
||||
|
|
@ -87,7 +82,7 @@ void register_code16(uint16_t code) {
|
|||
register_code(code);
|
||||
}
|
||||
|
||||
void unregister_code16(uint16_t code) {
|
||||
__attribute__((weak)) void unregister_code16(uint16_t code) {
|
||||
unregister_code(code);
|
||||
if (IS_MOD(code) || code == KC_NO) {
|
||||
do_code16(code, unregister_mods);
|
||||
|
|
@ -96,11 +91,13 @@ void unregister_code16(uint16_t code) {
|
|||
}
|
||||
}
|
||||
|
||||
void tap_code16(uint16_t code) {
|
||||
__attribute__((weak)) void tap_code16(uint16_t code) {
|
||||
register_code16(code);
|
||||
#if TAP_CODE_DELAY > 0
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
#endif
|
||||
if (code == KC_CAPS_LOCK) {
|
||||
wait_ms(TAP_HOLD_CAPS_DELAY);
|
||||
} else if (TAP_CODE_DELAY > 0) {
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
}
|
||||
unregister_code16(code);
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +260,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
#ifdef TAP_DANCE_ENABLE
|
||||
process_tap_dance(keycode, record) &&
|
||||
#endif
|
||||
#if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
|
||||
#if defined(UNICODE_COMMON_ENABLE)
|
||||
process_unicode_common(keycode, record) &&
|
||||
#endif
|
||||
#ifdef LEADER_ENABLE
|
||||
|
|
@ -306,12 +303,12 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
#ifndef NO_RESET
|
||||
case RESET:
|
||||
case QK_BOOTLOADER:
|
||||
reset_keyboard();
|
||||
return false;
|
||||
#endif
|
||||
#ifndef NO_DEBUG
|
||||
case DEBUG:
|
||||
case QK_DEBUG_TOGGLE:
|
||||
debug_enable ^= 1;
|
||||
if (debug_enable) {
|
||||
print("DEBUG: enabled.\n");
|
||||
|
|
@ -320,7 +317,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
}
|
||||
#endif
|
||||
return false;
|
||||
case EEPROM_RESET:
|
||||
case QK_CLEAR_EEPROM:
|
||||
eeconfig_init();
|
||||
return false;
|
||||
#ifdef VELOCIKEY_ENABLE
|
||||
|
|
@ -372,101 +369,9 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_
|
|||
|
||||
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); }
|
||||
|
||||
void matrix_init_quantum() {
|
||||
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_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_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
|
||||
|
||||
matrix_init_kb();
|
||||
}
|
||||
|
||||
void matrix_scan_quantum() {
|
||||
#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 LED_MATRIX_ENABLE
|
||||
led_matrix_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
|
||||
|
||||
matrix_scan_kb();
|
||||
}
|
||||
|
||||
#ifdef HD44780_ENABLED
|
||||
# include "hd44780.h"
|
||||
#endif
|
||||
// TODO: remove legacy api
|
||||
void matrix_init_quantum() { matrix_init_kb(); }
|
||||
void matrix_scan_quantum() { matrix_scan_kb(); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Override these functions in your keymap file to play different tunes on
|
||||
|
|
@ -502,14 +407,7 @@ void suspend_power_down_quantum(void) {
|
|||
# endif
|
||||
|
||||
// Turn off LED indicators
|
||||
uint8_t leds_off = 0;
|
||||
# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
|
||||
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);
|
||||
led_suspend();
|
||||
|
||||
// Turn off audio
|
||||
# ifdef AUDIO_ENABLE
|
||||
|
|
@ -560,7 +458,7 @@ __attribute__((weak)) void suspend_wakeup_init_quantum(void) {
|
|||
#endif
|
||||
|
||||
// Restore LED indicators
|
||||
led_set(host_keyboard_leds());
|
||||
led_wakeup();
|
||||
|
||||
// Wake up underglow
|
||||
#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,10 @@ extern layer_state_t layer_state;
|
|||
# include "process_unicodemap.h"
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE_COMMON_ENABLE
|
||||
# include "process_unicode_common.h"
|
||||
#endif
|
||||
|
||||
#ifdef KEY_OVERRIDE_ENABLE
|
||||
# include "process_key_override.h"
|
||||
#endif
|
||||
|
|
@ -249,11 +253,6 @@ void register_code16(uint16_t code);
|
|||
void unregister_code16(uint16_t code);
|
||||
void tap_code16(uint16_t code);
|
||||
|
||||
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);
|
||||
|
||||
const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad);
|
||||
const char *get_u8_str(uint8_t curr_num, char curr_pad);
|
||||
const char *get_u16_str(uint16_t curr_num, char curr_pad);
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ enum quantum_keycodes {
|
|||
QK_RALT = 0x1400,
|
||||
QK_RGUI = 0x1800,
|
||||
QK_MODS_MAX = 0x1FFF,
|
||||
QK_FUNCTION = 0x2000,
|
||||
QK_FUNCTION_MAX = 0x2FFF,
|
||||
QK_MACRO = 0x3000,
|
||||
QK_MACRO_MAX = 0x3FFF,
|
||||
QK_LAYER_TAP = 0x4000,
|
||||
QK_LAYER_TAP_MAX = 0x4FFF,
|
||||
QK_TO = 0x5000,
|
||||
|
|
@ -80,8 +76,8 @@ enum quantum_keycodes {
|
|||
QK_UNICODEMAP_PAIR_MAX = 0xFFFF,
|
||||
|
||||
// Loose keycodes - to be used directly
|
||||
RESET = 0x5C00,
|
||||
DEBUG, // 5C01
|
||||
QK_BOOTLOADER = 0x5C00,
|
||||
QK_DEBUG_TOGGLE, // 5C01
|
||||
|
||||
// Magic
|
||||
MAGIC_SWAP_CONTROL_CAPSLOCK, // 5C02
|
||||
|
|
@ -106,7 +102,7 @@ enum quantum_keycodes {
|
|||
MAGIC_TOGGLE_ALT_GUI, // 5C15
|
||||
|
||||
// Grave Escape
|
||||
GRAVE_ESC, // 5C16
|
||||
QK_GRAVE_ESCAPE, // 5C16
|
||||
|
||||
// Auto Shift
|
||||
KC_ASUP, // 5C17
|
||||
|
|
@ -379,7 +375,7 @@ enum quantum_keycodes {
|
|||
OUT_USB, // 5CDE
|
||||
|
||||
// Clear EEPROM
|
||||
EEPROM_RESET, // 5CDF
|
||||
QK_CLEAR_EEPROM, // 5CDF
|
||||
|
||||
// Unicode
|
||||
UNICODE_MODE_FORWARD, // 5CE0
|
||||
|
|
@ -597,6 +593,8 @@ enum quantum_keycodes {
|
|||
MACRO_30,
|
||||
MACRO_31,
|
||||
|
||||
MAGIC_TOGGLE_CONTROL_CAPSLOCK,
|
||||
|
||||
// Start of custom keycode range for keyboards and keymaps - always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
|
@ -708,15 +706,11 @@ enum quantum_keycodes {
|
|||
#define A(kc) LALT(kc)
|
||||
#define G(kc) LGUI(kc)
|
||||
|
||||
// Deprecated - do not use
|
||||
#define F(kc) (QK_FUNCTION | (kc))
|
||||
#define M(kc) (QK_MACRO | (kc))
|
||||
#define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc))
|
||||
#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
|
||||
#define QK_GESC QK_GRAVE_ESCAPE
|
||||
|
||||
#define KC_GESC GRAVE_ESC
|
||||
|
||||
#define EEP_RST EEPROM_RESET
|
||||
#define QK_BOOT QK_BOOTLOADER
|
||||
#define DB_TOGG QK_DEBUG_TOGGLE
|
||||
#define EE_CLR QK_CLEAR_EEPROM
|
||||
|
||||
// Audio Clicky aliases
|
||||
#define CK_TOGG CLICKY_TOGGLE
|
||||
|
|
@ -749,6 +743,7 @@ enum quantum_keycodes {
|
|||
#define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK
|
||||
#define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL
|
||||
#define CL_CAPS MAGIC_UNCAPSLOCK_TO_CONTROL
|
||||
#define CL_TOGG MAGIC_TOGGLE_CONTROL_CAPSLOCK
|
||||
|
||||
#define LCG_SWP MAGIC_SWAP_LCTL_LGUI
|
||||
#define LCG_NRM MAGIC_UNSWAP_LCTL_LGUI
|
||||
|
|
@ -961,3 +956,5 @@ enum quantum_keycodes {
|
|||
#define PB_32 PROGRAMMABLE_BUTTON_32
|
||||
#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1
|
||||
#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32
|
||||
|
||||
#include "quantum_keycodes_legacy.h"
|
||||
|
|
|
|||
13
quantum/quantum_keycodes_legacy.h
Normal file
13
quantum/quantum_keycodes_legacy.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Deprecated Quantum keycodes
|
||||
|
||||
#define RESET QK_BOOTLOADER
|
||||
#define DEBUG QK_DEBUG_TOGGLE
|
||||
#define GRAVE_ESC QK_GRAVE_ESCAPE
|
||||
#define EEPROM_RESET QK_CLEAR_EEPROM
|
||||
|
||||
#define KC_GESC QK_GRAVE_ESCAPE
|
||||
#define EEP_RST QK_CLEAR_EEPROM
|
||||
|
|
@ -31,6 +31,10 @@ static bool PIXEL_FRACTAL(effect_params_t* params) {
|
|||
|
||||
inline uint32_t interval(void) { return 3000 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); }
|
||||
|
||||
if (params->init) {
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
}
|
||||
|
||||
RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv);
|
||||
for (uint8_t h = 0; h < MATRIX_ROWS; ++h) {
|
||||
for (uint8_t l = 0; l < MID_COL - 1; ++l) { // Light and move left columns outwards
|
||||
|
|
|
|||
|
|
@ -275,12 +275,8 @@ static void rgb_task_timers(void) {
|
|||
|
||||
// Update double buffer timers
|
||||
#if RGB_DISABLE_TIMEOUT > 0
|
||||
if (rgb_anykey_timer < UINT32_MAX) {
|
||||
if (UINT32_MAX - deltaTime < rgb_anykey_timer) {
|
||||
rgb_anykey_timer = UINT32_MAX;
|
||||
} else {
|
||||
rgb_anykey_timer += deltaTime;
|
||||
}
|
||||
if (rgb_anykey_timer + deltaTime <= UINT32_MAX) {
|
||||
rgb_anykey_timer += deltaTime;
|
||||
}
|
||||
#endif // RGB_DISABLE_TIMEOUT > 0
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "matrix.h"
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@ enum serial_transaction_id {
|
|||
PUT_ST7565,
|
||||
#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
|
||||
|
||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
GET_POINTING_CHECKSUM,
|
||||
GET_POINTING_DATA,
|
||||
PUT_POINTING_CPI,
|
||||
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
PUT_RPC_INFO,
|
||||
PUT_RPC_REQ_DATA,
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@
|
|||
#define sizeof_member(type, member) sizeof(((type *)NULL)->member)
|
||||
|
||||
#define trans_initiator2target_initializer_cb(member, cb) \
|
||||
{ &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb }
|
||||
{ sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb }
|
||||
#define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL)
|
||||
|
||||
#define trans_target2initiator_initializer_cb(member, cb) \
|
||||
{ &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
|
||||
{ 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
|
||||
#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
|
||||
|
||||
#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
|
||||
|
|
@ -578,12 +578,89 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
|
|||
|
||||
#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// POINTING
|
||||
|
||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
static bool pointing_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||
# if defined(POINTING_DEVICE_LEFT)
|
||||
if (is_keyboard_left()) {
|
||||
return true;
|
||||
}
|
||||
# elif defined(POINTING_DEVICE_RIGHT)
|
||||
if (!is_keyboard_left()) {
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
static uint32_t last_update = 0;
|
||||
static uint16_t last_cpi = 0;
|
||||
report_mouse_t temp_state;
|
||||
uint16_t temp_cpi;
|
||||
bool okay = read_if_checksum_mismatch(GET_POINTING_CHECKSUM, GET_POINTING_DATA, &last_update, &temp_state, &split_shmem->pointing.report, sizeof(temp_state));
|
||||
if (okay) pointing_device_set_shared_report(temp_state);
|
||||
temp_cpi = pointing_device_get_shared_cpi();
|
||||
if (temp_cpi && memcmp(&last_cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
|
||||
memcpy(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi));
|
||||
okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi));
|
||||
if (okay) {
|
||||
last_cpi = temp_cpi;
|
||||
}
|
||||
}
|
||||
return okay;
|
||||
}
|
||||
|
||||
extern const pointing_device_driver_t pointing_device_driver;
|
||||
|
||||
static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||
# if defined(POINTING_DEVICE_LEFT)
|
||||
if (!is_keyboard_left()) {
|
||||
return;
|
||||
}
|
||||
# elif defined(POINTING_DEVICE_RIGHT)
|
||||
if (is_keyboard_left()) {
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
report_mouse_t temp_report;
|
||||
uint16_t temp_cpi;
|
||||
# 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
|
||||
temp_cpi = !pointing_device_driver.get_cpi ? 0 : pointing_device_driver.get_cpi(); // check for NULL
|
||||
if (split_shmem->pointing.cpi && memcmp(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
|
||||
if (pointing_device_driver.set_cpi) {
|
||||
pointing_device_driver.set_cpi(split_shmem->pointing.cpi);
|
||||
}
|
||||
}
|
||||
memset(&temp_report, 0, sizeof(temp_report));
|
||||
temp_report = pointing_device_driver.get_report(temp_report);
|
||||
memcpy(&split_shmem->pointing.report, &temp_report, sizeof(temp_report));
|
||||
// Now update the checksum given that the pointing has been written to
|
||||
split_shmem->pointing.checksum = crc8(&temp_report, sizeof(temp_report));
|
||||
}
|
||||
|
||||
# define TRANSACTIONS_POINTING_MASTER() TRANSACTION_HANDLER_MASTER(pointing)
|
||||
# define TRANSACTIONS_POINTING_SLAVE() TRANSACTION_HANDLER_SLAVE(pointing)
|
||||
# define TRANSACTIONS_POINTING_REGISTRATIONS [GET_POINTING_CHECKSUM] = trans_target2initiator_initializer(pointing.checksum), [GET_POINTING_DATA] = trans_target2initiator_initializer(pointing.report), [PUT_POINTING_CPI] = trans_initiator2target_initializer(pointing.cpi),
|
||||
|
||||
#else // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
# define TRANSACTIONS_POINTING_MASTER()
|
||||
# define TRANSACTIONS_POINTING_SLAVE()
|
||||
# define TRANSACTIONS_POINTING_REGISTRATIONS
|
||||
|
||||
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
uint8_t dummy;
|
||||
split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
||||
// Set defaults
|
||||
[0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0},
|
||||
[0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {0, 0, 0, 0, 0},
|
||||
|
||||
#ifdef USE_I2C
|
||||
[I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id),
|
||||
|
|
@ -604,6 +681,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
|||
TRANSACTIONS_WPM_REGISTRATIONS
|
||||
TRANSACTIONS_OLED_REGISTRATIONS
|
||||
TRANSACTIONS_ST7565_REGISTRATIONS
|
||||
TRANSACTIONS_POINTING_REGISTRATIONS
|
||||
// clang-format on
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
|
|
@ -629,6 +707,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
|
|||
TRANSACTIONS_WPM_MASTER();
|
||||
TRANSACTIONS_OLED_MASTER();
|
||||
TRANSACTIONS_ST7565_MASTER();
|
||||
TRANSACTIONS_POINTING_MASTER();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -647,6 +726,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
|
|||
TRANSACTIONS_WPM_SLAVE();
|
||||
TRANSACTIONS_OLED_SLAVE();
|
||||
TRANSACTIONS_ST7565_SLAVE();
|
||||
TRANSACTIONS_POINTING_SLAVE();
|
||||
}
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const voi
|
|||
|
||||
// Split transaction Descriptor
|
||||
typedef struct _split_transaction_desc_t {
|
||||
uint8_t * status;
|
||||
uint8_t initiator2target_buffer_size;
|
||||
uint16_t initiator2target_offset;
|
||||
uint8_t target2initiator_buffer_size;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ bool transport_execute_transaction(int8_t id, const void *initiator2target_buf,
|
|||
memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);
|
||||
}
|
||||
|
||||
if (soft_serial_transaction(id) != TRANSACTION_END) {
|
||||
if (!soft_serial_transaction(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,15 @@ typedef struct _split_mods_sync_t {
|
|||
} split_mods_sync_t;
|
||||
#endif // SPLIT_MODS_ENABLE
|
||||
|
||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
# include "pointing_device.h"
|
||||
typedef struct _split_slave_pointing_sync_t {
|
||||
uint8_t checksum;
|
||||
report_mouse_t report;
|
||||
uint16_t cpi;
|
||||
} split_slave_pointing_sync_t;
|
||||
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
typedef struct _rpc_sync_info_t {
|
||||
int8_t transaction_id;
|
||||
|
|
@ -173,6 +182,10 @@ typedef struct _split_shared_memory_t {
|
|||
uint8_t current_st7565_state;
|
||||
#endif // ST7565_ENABLE(OLED_ENABLE) && defined(SPLIT_ST7565_ENABLE)
|
||||
|
||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
split_slave_pointing_sync_t pointing;
|
||||
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
rpc_sync_info_t rpc_info;
|
||||
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
|
||||
|
|
|
|||
|
|
@ -244,12 +244,12 @@ _Static_assert(KC_LT == 0x0236, "");
|
|||
_Static_assert(KC_GT == 0x0237, "");
|
||||
_Static_assert(KC_QUES == 0x0238, "");
|
||||
|
||||
_Static_assert(RESET == 0x5C00, "");
|
||||
_Static_assert(DEBUG == 0x5C01, "");
|
||||
_Static_assert(QK_BOOTLOADER == 0x5C00, "");
|
||||
_Static_assert(QK_DEBUG_TOGGLE == 0x5C01, "");
|
||||
|
||||
_Static_assert(MAGIC_TOGGLE_NKRO == 0x5C14, "");
|
||||
|
||||
_Static_assert(KC_GESC == 0x5C16, "");
|
||||
_Static_assert(QK_GRAVE_ESCAPE == 0x5C16, "");
|
||||
|
||||
_Static_assert(AU_ON == 0x5C1D, "");
|
||||
_Static_assert(AU_OFF == 0x5C1E, "");
|
||||
|
|
|
|||
|
|
@ -22,33 +22,37 @@
|
|||
// WPM Stuff
|
||||
static uint8_t current_wpm = 0;
|
||||
static uint32_t wpm_timer = 0;
|
||||
#ifndef WPM_UNFILTERED
|
||||
static uint32_t smoothing_timer = 0;
|
||||
#endif
|
||||
|
||||
/* The WPM calculation works by specifying a certain number of 'periods' inside
|
||||
* a ring buffer, and we count the number of keypresses which occur in each of
|
||||
* those periods. Then to calculate WPM, we add up all of the keypresses in
|
||||
* the whole ring buffer, divide by the number of keypresses in a 'word', and
|
||||
* then adjust for how much time is captured by our ring buffer. Right now
|
||||
* the ring buffer is hardcoded below to be six half-second periods, accounting
|
||||
* for a total WPM sampling period of up to three seconds of typing.
|
||||
* then adjust for how much time is captured by our ring buffer. The size
|
||||
* of the ring buffer can be configured using the keymap configuration
|
||||
* value `WPM_SAMPLE_PERIODS`.
|
||||
*
|
||||
* Whenever our WPM drops to absolute zero due to no typing occurring within
|
||||
* any contiguous three seconds, we reset and start measuring fresh,
|
||||
* which lets our WPM immediately reach the correct value even before a full
|
||||
* three second sampling buffer has been filled.
|
||||
*/
|
||||
#define MAX_PERIODS (WPM_SAMPLE_PERIODS)
|
||||
#define PERIOD_DURATION (1000 * WPM_SAMPLE_SECONDS / MAX_PERIODS)
|
||||
#define LATENCY (100)
|
||||
static int8_t period_presses[MAX_PERIODS] = {0};
|
||||
|
||||
static int16_t period_presses[MAX_PERIODS] = {0};
|
||||
static uint8_t current_period = 0;
|
||||
static uint8_t periods = 1;
|
||||
|
||||
#if !defined(WPM_UNFILTERED)
|
||||
static uint8_t prev_wpm = 0;
|
||||
static uint8_t next_wpm = 0;
|
||||
/* LATENCY is used as part of filtering, and controls how quickly the reported
|
||||
* WPM trails behind our actual instantaneous measured WPM value, and is
|
||||
* defined in milliseconds. So for LATENCY == 100, the displayed WPM is
|
||||
* smoothed out over periods of 0.1 seconds. This results in a nice,
|
||||
* smoothly-moving reported WPM value which nevertheless is never more than
|
||||
* 0.1 seconds behind the typist's actual current WPM.
|
||||
*
|
||||
* LATENCY is not used if WPM_UNFILTERED is defined.
|
||||
*/
|
||||
# define LATENCY (100)
|
||||
static uint32_t smoothing_timer = 0;
|
||||
static uint8_t prev_wpm = 0;
|
||||
static uint8_t next_wpm = 0;
|
||||
#endif
|
||||
|
||||
void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
|
||||
|
|
@ -71,7 +75,7 @@ __attribute__((weak)) bool wpm_keycode_user(uint16_t keycode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef WPM_ALLOW_COUNT_REGRESSION
|
||||
#if defined(WPM_ALLOW_COUNT_REGRESSION)
|
||||
__attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
|
||||
bool weak_modded = (keycode >= QK_LCTL && keycode < QK_LSFT) || (keycode >= QK_RCTL && keycode < QK_RSFT);
|
||||
|
||||
|
|
@ -95,12 +99,12 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
|
|||
// Outside 'raw' mode we smooth results over time.
|
||||
|
||||
void update_wpm(uint16_t keycode) {
|
||||
if (wpm_keycode(keycode)) {
|
||||
if (wpm_keycode(keycode) && period_presses[current_period] < INT16_MAX) {
|
||||
period_presses[current_period]++;
|
||||
}
|
||||
#ifdef WPM_ALLOW_COUNT_REGRESSION
|
||||
#if defined(WPM_ALLOW_COUNT_REGRESSION)
|
||||
uint8_t regress = wpm_regress_count(keycode);
|
||||
if (regress) {
|
||||
if (regress && period_presses[current_period] > INT16_MIN) {
|
||||
period_presses[current_period]--;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -116,32 +120,41 @@ void decay_wpm(void) {
|
|||
}
|
||||
int32_t elapsed = timer_elapsed32(wpm_timer);
|
||||
uint32_t duration = (((periods)*PERIOD_DURATION) + elapsed);
|
||||
uint32_t wpm_now = (60000 * presses) / (duration * WPM_ESTIMATED_WORD_SIZE);
|
||||
wpm_now = (wpm_now > 240) ? 240 : wpm_now;
|
||||
int32_t wpm_now = (60000 * presses) / (duration * WPM_ESTIMATED_WORD_SIZE);
|
||||
|
||||
if (wpm_now < 0) // set some reasonable WPM measurement limits
|
||||
wpm_now = 0;
|
||||
if (wpm_now > 240) wpm_now = 240;
|
||||
|
||||
if (elapsed > PERIOD_DURATION) {
|
||||
current_period = (current_period + 1) % MAX_PERIODS;
|
||||
period_presses[current_period] = 0;
|
||||
periods = (periods < MAX_PERIODS - 1) ? periods + 1 : MAX_PERIODS - 1;
|
||||
elapsed = 0;
|
||||
/* if (wpm_timer == 0) { */
|
||||
wpm_timer = timer_read32();
|
||||
/* } else { */
|
||||
/* wpm_timer += PERIOD_DURATION; */
|
||||
/* } */
|
||||
wpm_timer = timer_read32();
|
||||
}
|
||||
if (presses < 2) // don't guess high WPM based on a single keypress.
|
||||
wpm_now = 0;
|
||||
|
||||
#if defined WPM_LAUNCH_CONTROL
|
||||
#if defined(WPM_LAUNCH_CONTROL)
|
||||
/*
|
||||
* If the `WPM_LAUNCH_CONTROL` option is enabled, then whenever our WPM
|
||||
* drops to absolute zero due to no typing occurring within our sample
|
||||
* ring buffer, we reset and start measuring fresh, which lets our WPM
|
||||
* immediately reach the correct value even before a full sampling buffer
|
||||
* has been filled.
|
||||
*/
|
||||
if (presses == 0) {
|
||||
current_period = 0;
|
||||
periods = 0;
|
||||
wpm_now = 0;
|
||||
current_period = 0;
|
||||
periods = 0;
|
||||
wpm_now = 0;
|
||||
period_presses[0] = 0;
|
||||
}
|
||||
#endif // WPM_LAUNCH_CONTROL
|
||||
|
||||
#ifndef WPM_UNFILTERED
|
||||
#if defined(WPM_UNFILTERED)
|
||||
current_wpm = wpm_now;
|
||||
#else
|
||||
int32_t latency = timer_elapsed32(smoothing_timer);
|
||||
if (latency > LATENCY) {
|
||||
smoothing_timer = timer_read32();
|
||||
|
|
@ -150,7 +163,5 @@ void decay_wpm(void) {
|
|||
}
|
||||
|
||||
current_wpm = prev_wpm + (latency * ((int)next_wpm - (int)prev_wpm) / LATENCY);
|
||||
#else
|
||||
current_wpm = wpm_now;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
# define WPM_SAMPLE_SECONDS 5
|
||||
#endif
|
||||
#ifndef WPM_SAMPLE_PERIODS
|
||||
# define WPM_SAMPLE_PERIODS 50
|
||||
# define WPM_SAMPLE_PERIODS 25
|
||||
#endif
|
||||
|
||||
bool wpm_keycode(uint16_t keycode);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue