Merge remote-tracking branch 'qmk/master' into merge-2022-09-10
This commit is contained in:
@@ -843,7 +843,7 @@ __attribute__((weak)) void register_code(uint8_t code) {
|
||||
# endif
|
||||
add_key(KC_CAPS_LOCK);
|
||||
send_keyboard_report();
|
||||
wait_ms(100);
|
||||
wait_ms(TAP_HOLD_CAPS_DELAY);
|
||||
del_key(KC_CAPS_LOCK);
|
||||
send_keyboard_report();
|
||||
}
|
||||
@@ -1084,20 +1084,15 @@ void clear_keyboard_but_mods_and_keys() {
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
bool is_tap_key(keypos_t key) {
|
||||
action_t action = layer_switch_get_action(key);
|
||||
return is_tap_action(action);
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
bool is_tap_record(keyrecord_t *record) {
|
||||
if (IS_NOEVENT(record->event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef COMBO_ENABLE
|
||||
action_t action;
|
||||
if (record->keycode) {
|
||||
|
||||
@@ -105,7 +105,6 @@ void clear_keyboard(void);
|
||||
void clear_keyboard_but_mods(void);
|
||||
void clear_keyboard_but_mods_and_keys(void);
|
||||
void layer_switch(uint8_t new_layer);
|
||||
bool is_tap_key(keypos_t key);
|
||||
bool is_tap_record(keyrecord_t *record);
|
||||
bool is_tap_action(action_t action);
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ enum layer_param_tap_op {
|
||||
#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer) / 4, 1 << ((layer) % 4), (on))
|
||||
#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR((layer) / 4, 1 << ((layer) % 4), (on))
|
||||
#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer) / 4, ~(1 << ((layer) % 4)), (on))
|
||||
#define ACTION_LAYER_GOTO(layer) ACTION_LAYER_SET(layer, ON_PRESS)
|
||||
#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4), (on))
|
||||
#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
|
||||
#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
|
||||
|
||||
@@ -41,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
|
||||
#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT)
|
||||
# define LAYER_STATE_32BIT
|
||||
# define LAYER_STATE_16BIT
|
||||
#endif
|
||||
|
||||
#if defined(LAYER_STATE_8BIT)
|
||||
|
||||
@@ -125,7 +125,7 @@ void action_tapping_process(keyrecord_t record) {
|
||||
/* return true when key event is processed or consumed. */
|
||||
bool process_tapping(keyrecord_t *keyp) {
|
||||
keyevent_t event = keyp->event;
|
||||
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
|
||||
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
|
||||
uint16_t tapping_keycode = get_record_keycode(&tapping_key, false);
|
||||
# endif
|
||||
|
||||
@@ -164,17 +164,15 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
* useful for long TAPPING_TERM but may prevent fast typing.
|
||||
*/
|
||||
// clang-format off
|
||||
# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
|
||||
# if defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
|
||||
else if (
|
||||
(
|
||||
(
|
||||
GET_TAPPING_TERM(tapping_keycode, &tapping_key) >= 500
|
||||
IS_RELEASED(event) && waiting_buffer_typed(event)
|
||||
# ifdef PERMISSIVE_HOLD_PER_KEY
|
||||
|| get_permissive_hold(tapping_keycode, &tapping_key)
|
||||
&& get_permissive_hold(tapping_keycode, &tapping_key)
|
||||
# elif defined(PERMISSIVE_HOLD)
|
||||
|| true
|
||||
&& true
|
||||
# endif
|
||||
) && IS_RELEASED(event) && waiting_buffer_typed(event)
|
||||
)
|
||||
// Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
|
||||
// unnecessarily and fixes them for Layer Taps.
|
||||
|
||||
@@ -144,6 +144,12 @@
|
||||
*/
|
||||
#define USSR_ANTHEM B__NOTE(_G6), B__NOTE(_C7), W__NOTE(_G6), H__NOTE(_A6), B__NOTE(_B6), W__NOTE(_E6), W__NOTE(_E6), B__NOTE(_A6), W__NOTE(_G6), H__NOTE(_F6), B__NOTE(_G6), W__NOTE(_C6), W__NOTE(_C6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_E6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_G6), B__NOTE(_F6), W__NOTE(_G6), W__NOTE(_A6), B__NOTE(_B6),
|
||||
|
||||
/* Title: Hymn Risen
|
||||
* Author/Composer: Terrance Andrew Davis
|
||||
* License: Public Domain
|
||||
*/
|
||||
#define TOS_HYMN_RISEN H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80)
|
||||
|
||||
/* Removed sounds
|
||||
+ This list is here solely for compatibility, so that removed songs don't just break things
|
||||
* If you think that any of these songs were wrongfully removed, let us know and provide
|
||||
|
||||
@@ -165,7 +165,7 @@ static void command_common_help(void) {
|
||||
}
|
||||
|
||||
static void print_version(void) {
|
||||
print(/* clang-format off */
|
||||
xprintf("%s", /* clang-format off */
|
||||
"\n\t- Version -\n"
|
||||
"VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
|
||||
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
|
||||
@@ -286,6 +286,7 @@ static void print_eeconfig(void) {
|
||||
".swap_grave_esc: %u\n"
|
||||
".swap_backslash_backspace: %u\n"
|
||||
".nkro: %u\n"
|
||||
".swap_escape_capslock: %u\n"
|
||||
|
||||
, kc.raw
|
||||
, kc.swap_control_capslock
|
||||
@@ -298,6 +299,7 @@ static void print_eeconfig(void) {
|
||||
, kc.swap_grave_esc
|
||||
, kc.swap_backslash_backspace
|
||||
, kc.nkro
|
||||
, kc.swap_escape_capslock
|
||||
); /* clang-format on */
|
||||
|
||||
# ifdef BACKLIGHT_ENABLE
|
||||
|
||||
@@ -146,7 +146,7 @@ bool command_proc(uint8_t code);
|
||||
#endif
|
||||
|
||||
#ifndef MAGIC_KEY_EEPROM_CLEAR
|
||||
# define MAGIC_KEY_EEPROM_CLEAR BSPACE
|
||||
# define MAGIC_KEY_EEPROM_CLEAR BACKSPACE
|
||||
#endif
|
||||
|
||||
#ifndef MAGIC_KEY_NKRO
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
// raw is the current key state
|
||||
// on entry cooked is the previous debounced state
|
||||
// on exit cooked is the current debounced state
|
||||
// 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);
|
||||
/**
|
||||
* @brief Debounce raw matrix events according to the choosen debounce algorithm.
|
||||
*
|
||||
* @param raw The current key state
|
||||
* @param cooked The debounced key state
|
||||
* @param num_rows Number of rows to debounce
|
||||
* @param changed True if raw has changed since the last call
|
||||
* @return true Cooked has new keychanges after debouncing
|
||||
* @return false Cooked is the same as before
|
||||
*/
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed);
|
||||
|
||||
void debounce_init(uint8_t num_rows);
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ static debounce_counter_t *debounce_counters;
|
||||
static fast_timer_t last_time;
|
||||
static bool counters_need_update;
|
||||
static bool matrix_need_update;
|
||||
static bool cooked_changed;
|
||||
|
||||
# define DEBOUNCE_ELAPSED 0
|
||||
|
||||
@@ -77,8 +78,9 @@ void debounce_free(void) {
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool updated_last = false;
|
||||
cooked_changed = false;
|
||||
|
||||
if (counters_need_update) {
|
||||
fast_timer_t now = timer_read_fast();
|
||||
@@ -102,6 +104,8 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
|
||||
transfer_matrix_values(raw, cooked, num_rows);
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
|
||||
@@ -123,7 +127,9 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],
|
||||
matrix_need_update = true;
|
||||
} else {
|
||||
// key-up: defer
|
||||
cooked[row] = (cooked[row] & ~col_mask) | (raw[row] & col_mask);
|
||||
matrix_row_t cooked_next = (cooked[row] & ~col_mask) | (raw[row] & col_mask);
|
||||
cooked_changed |= cooked_next ^ cooked[row];
|
||||
cooked[row] = cooked_next;
|
||||
}
|
||||
} else {
|
||||
debounce_pointer->time -= elapsed_time;
|
||||
@@ -152,6 +158,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
if (debounce_pointer->pressed) {
|
||||
// key-down: eager
|
||||
cooked[row] ^= col_mask;
|
||||
cooked_changed = true;
|
||||
}
|
||||
}
|
||||
} else if (debounce_pointer->time != DEBOUNCE_ELAPSED) {
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
#include "matrix.h"
|
||||
#include "quantum.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void debounce_init(uint8_t num_rows) {}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
for (int i = 0; i < num_rows; i++) {
|
||||
cooked[i] = raw[i];
|
||||
}
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool cooked_changed = memcmp(raw, cooked, sizeof(matrix_row_t) * num_rows) != 0;
|
||||
|
||||
memcpy(cooked, raw, sizeof(matrix_row_t) * num_rows);
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
void debounce_free(void) {}
|
||||
|
||||
@@ -20,6 +20,7 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
|
||||
#include "matrix.h"
|
||||
#include "timer.h"
|
||||
#include "quantum.h"
|
||||
#include <string.h>
|
||||
#ifndef DEBOUNCE
|
||||
# define DEBOUNCE 5
|
||||
#endif
|
||||
@@ -30,18 +31,23 @@ static fast_timer_t debouncing_time;
|
||||
|
||||
void debounce_init(uint8_t num_rows) {}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool cooked_changed = false;
|
||||
|
||||
if (changed) {
|
||||
debouncing = true;
|
||||
debouncing_time = timer_read_fast();
|
||||
}
|
||||
|
||||
if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {
|
||||
for (int i = 0; i < num_rows; i++) {
|
||||
cooked[i] = raw[i];
|
||||
if (memcmp(cooked, raw, sizeof(matrix_row_t) * num_rows) != 0) {
|
||||
memcpy(cooked, raw, sizeof(matrix_row_t) * num_rows);
|
||||
cooked_changed = true;
|
||||
}
|
||||
debouncing = false;
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
void debounce_free(void) {}
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef uint8_t debounce_counter_t;
|
||||
static debounce_counter_t *debounce_counters;
|
||||
static fast_timer_t last_time;
|
||||
static bool counters_need_update;
|
||||
static bool cooked_changed;
|
||||
|
||||
# define DEBOUNCE_ELAPSED 0
|
||||
|
||||
@@ -70,8 +71,9 @@ void debounce_free(void) {
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool updated_last = false;
|
||||
cooked_changed = false;
|
||||
|
||||
if (counters_need_update) {
|
||||
fast_timer_t now = timer_read_fast();
|
||||
@@ -95,6 +97,8 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
|
||||
start_debounce_counters(raw, cooked, num_rows);
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
|
||||
@@ -104,8 +108,10 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
|
||||
if (*debounce_pointer <= elapsed_time) {
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
matrix_row_t cooked_next = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
|
||||
cooked_changed |= cooked[row] ^ cooked_next;
|
||||
cooked[row] = cooked_next;
|
||||
} else {
|
||||
*debounce_pointer -= elapsed_time;
|
||||
counters_need_update = true;
|
||||
|
||||
@@ -46,11 +46,12 @@ void debounce_free(void) {
|
||||
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;
|
||||
bool 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;
|
||||
bool cooked_changed = false;
|
||||
|
||||
uint8_t* countdown = countdowns;
|
||||
|
||||
@@ -63,10 +64,13 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
} else if (*countdown > elapsed) {
|
||||
*countdown -= elapsed;
|
||||
} else if (*countdown) {
|
||||
cooked_changed |= cooked[row] ^ raw_row;
|
||||
cooked[row] = raw_row;
|
||||
*countdown = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
bool debounce_active(void) {
|
||||
|
||||
@@ -49,6 +49,7 @@ static debounce_counter_t *debounce_counters;
|
||||
static fast_timer_t last_time;
|
||||
static bool counters_need_update;
|
||||
static bool matrix_need_update;
|
||||
static bool cooked_changed;
|
||||
|
||||
# define DEBOUNCE_ELAPSED 0
|
||||
|
||||
@@ -71,8 +72,9 @@ void debounce_free(void) {
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool updated_last = false;
|
||||
cooked_changed = false;
|
||||
|
||||
if (counters_need_update) {
|
||||
fast_timer_t now = timer_read_fast();
|
||||
@@ -96,6 +98,8 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
|
||||
transfer_matrix_values(raw, cooked, num_rows);
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
// If the current time is > debounce counter, set the counter to enable input.
|
||||
@@ -132,6 +136,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
existing_row ^= col_mask; // flip the bit.
|
||||
cooked_changed = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
|
||||
@@ -48,6 +48,7 @@ static bool matrix_need_update;
|
||||
static debounce_counter_t *debounce_counters;
|
||||
static fast_timer_t last_time;
|
||||
static bool counters_need_update;
|
||||
static bool cooked_changed;
|
||||
|
||||
# define DEBOUNCE_ELAPSED 0
|
||||
|
||||
@@ -67,8 +68,9 @@ void debounce_free(void) {
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
bool updated_last = false;
|
||||
cooked_changed = false;
|
||||
|
||||
if (counters_need_update) {
|
||||
fast_timer_t now = timer_read_fast();
|
||||
@@ -92,6 +94,8 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
|
||||
transfer_matrix_values(raw, cooked, num_rows);
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
// If the current time is > debounce counter, set the counter to enable input.
|
||||
@@ -123,8 +127,9 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
// determine new value basd on debounce pointer + raw value
|
||||
if (existing_row != raw_row) {
|
||||
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
cooked[row] = raw_row;
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
cooked[row] = raw_row;
|
||||
cooked_changed |= cooked[row] ^ raw[row];
|
||||
counters_need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,11 +125,15 @@ void DebounceTest::runDebounce(bool changed) {
|
||||
std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_));
|
||||
std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_));
|
||||
|
||||
debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
|
||||
bool cooked_changed = debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
|
||||
|
||||
if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
|
||||
FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
|
||||
}
|
||||
|
||||
if (std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)) && cooked_changed) {
|
||||
FAIL() << "Fatal error: debounce() did detect a wrong cooked matrix change at " << strTime() << "\noutput_matrix: cooked_changed=" << cooked_changed << "\n" << strMatrix(output_matrix_) << "\ncooked_matrix:\n" << strMatrix(cooked_matrix_);
|
||||
}
|
||||
}
|
||||
|
||||
void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
#include "via.h" // for default VIA_EEPROM_ADDR_END
|
||||
#include <string.h>
|
||||
|
||||
#ifdef VIA_ENABLE
|
||||
# include "via.h" // for VIA_EEPROM_CONFIG_END
|
||||
# define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END)
|
||||
#else
|
||||
# define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE)
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_ENABLE
|
||||
#include "vial.h"
|
||||
#endif
|
||||
@@ -60,13 +67,8 @@
|
||||
#endif
|
||||
|
||||
// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
|
||||
// default it start after VIA_EEPROM_CUSTOM_ADDR+VIA_EEPROM_CUSTOM_SIZE
|
||||
#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
|
||||
# ifdef VIA_EEPROM_CUSTOM_CONFIG_ADDR
|
||||
# define DYNAMIC_KEYMAP_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR + VIA_EEPROM_CUSTOM_CONFIG_SIZE)
|
||||
# else
|
||||
# error DYNAMIC_KEYMAP_EEPROM_ADDR not defined
|
||||
# endif
|
||||
# define DYNAMIC_KEYMAP_EEPROM_ADDR DYNAMIC_KEYMAP_EEPROM_START
|
||||
#endif
|
||||
|
||||
// Encoders are located right after the dynamic keymap
|
||||
@@ -130,6 +132,10 @@ _Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= DYNAMIC_KEYMAP_MACRO_EEPROM_ADD
|
||||
# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 1)
|
||||
#endif
|
||||
|
||||
#ifndef DYNAMIC_KEYMAP_MACRO_DELAY
|
||||
# define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY
|
||||
#endif
|
||||
|
||||
uint8_t dynamic_keymap_get_layer_count(void) {
|
||||
return DYNAMIC_KEYMAP_LAYER_COUNT;
|
||||
}
|
||||
@@ -271,18 +277,25 @@ void dynamic_keymap_reset(void) {
|
||||
#endif
|
||||
|
||||
// Reset the keymaps in EEPROM to what is in flash.
|
||||
// All keyboards using dynamic keymaps should define a layout
|
||||
// for the same number of layers as DYNAMIC_KEYMAP_LAYER_COUNT.
|
||||
for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) {
|
||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
||||
for (int column = 0; column < MATRIX_COLS; column++) {
|
||||
dynamic_keymap_set_keycode(layer, row, column, pgm_read_word(&keymaps[layer][row][column]));
|
||||
if (layer < keymap_layer_count()) {
|
||||
dynamic_keymap_set_keycode(layer, row, column, pgm_read_word(&keymaps[layer][row][column]));
|
||||
} else {
|
||||
dynamic_keymap_set_keycode(layer, row, column, KC_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ENCODER_MAP_ENABLE
|
||||
for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) {
|
||||
dynamic_keymap_set_encoder(layer, encoder, true, pgm_read_word(&encoder_map[layer][encoder][0]));
|
||||
dynamic_keymap_set_encoder(layer, encoder, false, pgm_read_word(&encoder_map[layer][encoder][1]));
|
||||
if (layer < encodermap_layer_count()) {
|
||||
dynamic_keymap_set_encoder(layer, encoder, true, pgm_read_word(&encoder_map[layer][encoder][0]));
|
||||
dynamic_keymap_set_encoder(layer, encoder, false, pgm_read_word(&encoder_map[layer][encoder][1]));
|
||||
} else {
|
||||
dynamic_keymap_set_encoder(layer, encoder, true, KC_TRANSPARENT);
|
||||
dynamic_keymap_set_encoder(layer, encoder, false, KC_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
#endif // ENCODER_MAP_ENABLE
|
||||
}
|
||||
@@ -554,7 +567,7 @@ void dynamic_keymap_macro_send(uint8_t id) {
|
||||
}
|
||||
} else {
|
||||
// If the char wasn't magic, just send it
|
||||
send_string(data);
|
||||
send_string_with_delay(data, DYNAMIC_KEYMAP_MACRO_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,27 +163,38 @@ static bool encoder_update(uint8_t index, uint8_t state) {
|
||||
index += thisHand;
|
||||
#endif
|
||||
encoder_pulses[i] += encoder_LUT[state & 0xF];
|
||||
|
||||
#ifdef ENCODER_DEFAULT_POS
|
||||
if ((encoder_pulses[i] >= resolution) || (encoder_pulses[i] <= -resolution) || ((state & 0x3) == ENCODER_DEFAULT_POS)) {
|
||||
if (encoder_pulses[i] >= 1) {
|
||||
#else
|
||||
if (encoder_pulses[i] >= resolution) {
|
||||
encoder_value[index]++;
|
||||
changed = true;
|
||||
#endif
|
||||
|
||||
encoder_value[index]++;
|
||||
changed = true;
|
||||
#ifdef ENCODER_MAP_ENABLE
|
||||
encoder_exec_mapping(index, ENCODER_COUNTER_CLOCKWISE);
|
||||
encoder_exec_mapping(index, ENCODER_COUNTER_CLOCKWISE);
|
||||
#else // ENCODER_MAP_ENABLE
|
||||
encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
|
||||
#endif // ENCODER_MAP_ENABLE
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENCODER_DEFAULT_POS
|
||||
if (encoder_pulses[i] <= -1) {
|
||||
#else
|
||||
if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
|
||||
encoder_value[index]--;
|
||||
changed = true;
|
||||
#endif
|
||||
encoder_value[index]--;
|
||||
changed = true;
|
||||
#ifdef ENCODER_MAP_ENABLE
|
||||
encoder_exec_mapping(index, ENCODER_CLOCKWISE);
|
||||
encoder_exec_mapping(index, ENCODER_CLOCKWISE);
|
||||
#else // ENCODER_MAP_ENABLE
|
||||
encoder_update_kb(index, ENCODER_CLOCKWISE);
|
||||
#endif // ENCODER_MAP_ENABLE
|
||||
}
|
||||
encoder_pulses[i] %= resolution;
|
||||
}
|
||||
encoder_pulses[i] %= resolution;
|
||||
#ifdef ENCODER_DEFAULT_POS
|
||||
if ((state & 0x3) == ENCODER_DEFAULT_POS) {
|
||||
encoder_pulses[i] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -218,6 +218,12 @@ static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief matrix_setup
|
||||
@@ -393,12 +399,9 @@ void keyboard_init(void) {
|
||||
#ifdef ENCODER_ENABLE
|
||||
encoder_init();
|
||||
#endif
|
||||
#ifdef STENO_ENABLE
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
steno_init();
|
||||
#endif
|
||||
#ifdef POINTING_DEVICE_ENABLE
|
||||
pointing_device_init();
|
||||
#endif
|
||||
#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
|
||||
keymap_config.nkro = 1;
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
@@ -415,6 +418,10 @@ void keyboard_init(void) {
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_post_init();
|
||||
#endif
|
||||
#ifdef POINTING_DEVICE_ENABLE
|
||||
// init after split init
|
||||
pointing_device_init();
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
|
||||
debug_enable = true;
|
||||
@@ -437,64 +444,74 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Perform scan of keyboard matrix
|
||||
*
|
||||
* Any detected changes in state are sent out as part of the processing
|
||||
/**
|
||||
* @brief Generates a tick event at a maximum rate of 1KHz that drives the
|
||||
* internal QMK state machine.
|
||||
*/
|
||||
bool matrix_scan_task(void) {
|
||||
static matrix_row_t matrix_prev[MATRIX_ROWS];
|
||||
matrix_row_t matrix_row = 0;
|
||||
matrix_row_t matrix_change = 0;
|
||||
#ifdef QMK_KEYS_PER_SCAN
|
||||
uint8_t keys_processed = 0;
|
||||
#endif
|
||||
|
||||
uint8_t matrix_changed = matrix_scan();
|
||||
if (matrix_changed) last_matrix_activity_trigger();
|
||||
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
matrix_row = matrix_get_row(r);
|
||||
matrix_change = matrix_row ^ matrix_prev[r];
|
||||
if (matrix_change) {
|
||||
#ifdef MATRIX_HAS_GHOST
|
||||
if (has_ghost_in_row(r, matrix_row)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (debug_matrix) matrix_print();
|
||||
matrix_row_t col_mask = 1;
|
||||
for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
|
||||
if (matrix_change & col_mask) {
|
||||
if (should_process_keypress()) {
|
||||
action_exec((keyevent_t){
|
||||
.key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
|
||||
});
|
||||
}
|
||||
// record a processed key
|
||||
matrix_prev[r] ^= col_mask;
|
||||
|
||||
switch_events(r, c, (matrix_row & col_mask));
|
||||
|
||||
#ifdef QMK_KEYS_PER_SCAN
|
||||
// only jump out if we have processed "enough" keys.
|
||||
if (++keys_processed >= QMK_KEYS_PER_SCAN)
|
||||
#endif
|
||||
// process a key per task call
|
||||
goto MATRIX_LOOP_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// call with pseudo tick event when no real key event.
|
||||
#ifdef QMK_KEYS_PER_SCAN
|
||||
// we can get here with some keys processed now.
|
||||
if (!keys_processed)
|
||||
#endif
|
||||
static inline void generate_tick_event(void) {
|
||||
static uint16_t last_tick = 0;
|
||||
const uint16_t now = timer_read();
|
||||
if (TIMER_DIFF_16(now, last_tick) != 0) {
|
||||
action_exec(TICK_EVENT);
|
||||
last_tick = now;
|
||||
}
|
||||
}
|
||||
|
||||
MATRIX_LOOP_END:
|
||||
/**
|
||||
* @brief This task scans the keyboards matrix and processes any key presses
|
||||
* that occur.
|
||||
*
|
||||
* @return true Matrix did change
|
||||
* @return false Matrix didn't change
|
||||
*/
|
||||
static bool matrix_task(void) {
|
||||
static matrix_row_t matrix_previous[MATRIX_ROWS];
|
||||
|
||||
matrix_scan();
|
||||
|
||||
bool matrix_changed = false;
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS && !matrix_changed; row++) {
|
||||
matrix_changed |= matrix_previous[row] ^ matrix_get_row(row);
|
||||
}
|
||||
|
||||
matrix_scan_perf_task();
|
||||
|
||||
// Short-circuit the complete matrix processing if it is not necessary
|
||||
if (!matrix_changed) {
|
||||
generate_tick_event();
|
||||
return matrix_changed;
|
||||
}
|
||||
|
||||
if (debug_config.matrix) {
|
||||
matrix_print();
|
||||
}
|
||||
|
||||
const bool process_keypress = should_process_keypress();
|
||||
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||
const matrix_row_t current_row = matrix_get_row(row);
|
||||
const matrix_row_t row_changes = current_row ^ matrix_previous[row];
|
||||
|
||||
if (!row_changes || has_ghost_in_row(row, current_row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
matrix_row_t col_mask = 1;
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++, col_mask <<= 1) {
|
||||
if (row_changes & col_mask) {
|
||||
const bool key_pressed = current_row & col_mask;
|
||||
|
||||
if (process_keypress) {
|
||||
action_exec(MAKE_KEYEVENT(row, col, key_pressed));
|
||||
}
|
||||
|
||||
switch_events(row, col, key_pressed);
|
||||
}
|
||||
}
|
||||
|
||||
matrix_previous[row] = current_row;
|
||||
}
|
||||
|
||||
return matrix_changed;
|
||||
}
|
||||
|
||||
@@ -573,20 +590,12 @@ void quantum_task(void) {
|
||||
#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.
|
||||
*/
|
||||
/** \brief Main task that is repeatedly called as fast as possible. */
|
||||
void keyboard_task(void) {
|
||||
bool matrix_changed = matrix_scan_task();
|
||||
(void)matrix_changed;
|
||||
const bool matrix_changed = matrix_task();
|
||||
if (matrix_changed) {
|
||||
last_matrix_activity_trigger();
|
||||
}
|
||||
|
||||
quantum_task();
|
||||
|
||||
@@ -608,8 +617,10 @@ void keyboard_task(void) {
|
||||
#endif
|
||||
|
||||
#ifdef ENCODER_ENABLE
|
||||
bool encoders_changed = encoder_read();
|
||||
if (encoders_changed) last_encoder_activity_trigger();
|
||||
const bool encoders_changed = encoder_read();
|
||||
if (encoders_changed) {
|
||||
last_encoder_activity_trigger();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OLED_ENABLE
|
||||
|
||||
@@ -71,9 +71,15 @@ static inline bool IS_RELEASED(keyevent_t event) {
|
||||
|
||||
/* Common keyevent object factory */
|
||||
#define MAKE_KEYPOS(row_num, col_num) ((keypos_t){.row = (row_num), .col = (col_num)})
|
||||
|
||||
/**
|
||||
* @brief Constructs a key event for a pressed or released key.
|
||||
*/
|
||||
#define MAKE_KEYEVENT(row_num, col_num, press) ((keyevent_t){.key = MAKE_KEYPOS((row_num), (col_num)), .pressed = (press), .time = (timer_read() | 1)})
|
||||
|
||||
/* Tick event */
|
||||
/**
|
||||
* @brief Constructs a internal tick event that is used to drive the internal QMK state machine.
|
||||
*/
|
||||
#define TICK_EVENT MAKE_KEYEVENT(KEYLOC_TICK, KEYLOC_TICK, false)
|
||||
|
||||
#ifdef ENCODER_MAP_ENABLE
|
||||
|
||||
@@ -29,6 +29,8 @@ uint16_t keycode_config(uint16_t keycode) {
|
||||
case KC_LOCKING_CAPS_LOCK:
|
||||
if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
|
||||
return KC_LEFT_CTRL;
|
||||
} else if (keymap_config.swap_escape_capslock) {
|
||||
return KC_ESCAPE;
|
||||
}
|
||||
return keycode;
|
||||
case KC_LEFT_CTRL:
|
||||
@@ -96,6 +98,8 @@ uint16_t keycode_config(uint16_t keycode) {
|
||||
case KC_ESCAPE:
|
||||
if (keymap_config.swap_grave_esc) {
|
||||
return KC_GRAVE;
|
||||
} else if (keymap_config.swap_escape_capslock) {
|
||||
return KC_CAPS_LOCK;
|
||||
}
|
||||
return KC_ESCAPE;
|
||||
case KC_BACKSLASH:
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef union {
|
||||
bool swap_lctl_lgui : 1;
|
||||
bool swap_rctl_rgui : 1;
|
||||
bool oneshot_enable : 1;
|
||||
bool swap_escape_capslock : 1;
|
||||
};
|
||||
} keymap_config_t;
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "quantum_keycodes.h"
|
||||
|
||||
// Gross hack, remove me and change RESET keycode to QK_BOOT
|
||||
#if defined(MCU_RP)
|
||||
# undef RESET
|
||||
#endif
|
||||
|
||||
// translates key to keycode
|
||||
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
|
||||
|
||||
@@ -55,3 +60,5 @@ extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
// Ensure we have a forward declaration for the encoder map
|
||||
# include "encoder.h"
|
||||
#endif
|
||||
|
||||
#include "keymap_introspection.h"
|
||||
|
||||
@@ -47,10 +47,9 @@ action_t action_for_keycode(uint16_t keycode) {
|
||||
keycode = keycode_config(keycode);
|
||||
|
||||
action_t action = {};
|
||||
uint8_t action_layer, when, mod;
|
||||
uint8_t action_layer, mod;
|
||||
|
||||
(void)action_layer;
|
||||
(void)when;
|
||||
(void)mod;
|
||||
|
||||
switch (keycode) {
|
||||
@@ -85,9 +84,8 @@ action_t action_for_keycode(uint16_t keycode) {
|
||||
break;
|
||||
case QK_TO ... QK_TO_MAX:;
|
||||
// Layer set "GOTO"
|
||||
when = (keycode >> 0x4) & 0x3;
|
||||
action_layer = keycode & 0xF;
|
||||
action.code = ACTION_LAYER_SET(action_layer, when);
|
||||
action_layer = keycode & 0xFF;
|
||||
action.code = ACTION_LAYER_GOTO(action_layer);
|
||||
break;
|
||||
case QK_MOMENTARY ... QK_MOMENTARY_MAX:;
|
||||
// Momentary action_layer
|
||||
|
||||
@@ -237,4 +237,4 @@
|
||||
#define BP_DDAG S(ALGR(BP_H)) // ‡
|
||||
#define BP_FORD S(ALGR(BP_F)) // ª
|
||||
// Row 5
|
||||
#define BP_NNBS S(ALGR(BP_)) // (narrow non-breaking space)
|
||||
#define BP_NNBS S(ALGR(KC_SPC)) // (narrow non-breaking space)
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
#define CZ_8 S(CZ_AACU) // 8
|
||||
#define CZ_9 S(CZ_IACU) // 9
|
||||
#define CZ_0 S(CZ_EACU) // 0
|
||||
#define CZ_PERC S(CZ_PLUS) // %
|
||||
#define CZ_PERC S(CZ_EQL) // %
|
||||
#define CZ_CARN S(CZ_ACUT) // ˇ (dead)
|
||||
// Row 2
|
||||
#define CZ_SLSH S(CZ_UACU) // /
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
/*
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
* │Z↔︎H│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │ │
|
||||
* │Z↔H│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤
|
||||
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ @ │ [ │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
@@ -40,7 +40,7 @@
|
||||
* └─────┴───┴─────┴─────┴─────────┴─────┴───┴───┴───┴───┴─────┘
|
||||
*/
|
||||
// Row 1
|
||||
#define JP_ZKHK KC_GRV // Zenkaku ↔︎ Hankaku ↔ Kanji (半角 ↔ 全角 ↔ 漢字)
|
||||
#define JP_ZKHK KC_GRV // Zenkaku ↔ Hankaku ↔ Kanji (半角 ↔ 全角 ↔ 漢字)
|
||||
#define JP_1 KC_1 // 1
|
||||
#define JP_2 KC_2 // 2
|
||||
#define JP_3 KC_3 // 3
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
#define KR_PIPE S(KR_WON) // |
|
||||
// Row 3
|
||||
#define KR_COLN S(KR_SCLN) // :
|
||||
#define KR_DQUO S(KR_COLN) // "
|
||||
#define KR_DQUO S(KR_QUOT) // "
|
||||
// Row 4
|
||||
#define KR_LABK S(KR_COMM) // <
|
||||
#define KR_RABK S(KR_DOT) // >
|
||||
|
||||
@@ -161,8 +161,8 @@
|
||||
#define LV_ACUT ALGR(LV_QUOT) // ´ (dead)
|
||||
// Row 4
|
||||
#define LV_ZCAR ALGR(LV_Z) // Ž
|
||||
#define LV_CCAR ALGR(LV_Z) // Č
|
||||
#define LV_NCED ALGR(LV_Z) // Ņ
|
||||
#define LV_CCAR ALGR(LV_C) // Č
|
||||
#define LV_NCED ALGR(LV_N) // Ņ
|
||||
|
||||
/* Shift+AltGr symbols
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ ` │ Ą │ Č │ Ę │ Ė │ Į │ Š │ Ų │ Ū │ 9 │ 0 │ - │ Ž │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ \ │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │ \ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
|
||||
* │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
|
||||
* │ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ │
|
||||
* ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
@@ -72,7 +72,7 @@
|
||||
#define LT_L KC_L // L
|
||||
#define LT_SCLN KC_SCLN // ;
|
||||
#define LT_QUOT KC_QUOT // '
|
||||
#define LT_BSLS KC_NUHS // (backslash)
|
||||
#define LT_BSLS KC_BSLS // (backslash)
|
||||
// Row 4
|
||||
#define LT_Z KC_Z // Z
|
||||
#define LT_X KC_X // X
|
||||
@@ -89,10 +89,10 @@
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ ~ │ │ │ │ │ │ │ │ │ ( │ ) │ _ │ │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ { │ } │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ : │ " │ | │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ { │ } │ | │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ : │ " │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
|
||||
* │ │ │ │ │ │ │ │ │ < │ > │ ? │ │
|
||||
* ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
@@ -102,12 +102,12 @@
|
||||
#define LT_TILD S(LT_GRV) // ~
|
||||
#define LT_LPRN S(LT_9) // (
|
||||
#define LT_RPRN S(LT_0) // )
|
||||
#define LT_UNDS S(LT_MINS) // *
|
||||
#define LT_UNDS S(LT_MINS) // _
|
||||
// Row 2
|
||||
#define LT_LCBR S(LT_LBRC) // {
|
||||
#define LT_RCBR S(LT_RBRC) // }
|
||||
// Row 3
|
||||
#define LT_COLN S(LT_SCLN) // ;
|
||||
#define LT_COLN S(LT_SCLN) // :
|
||||
#define LT_DQUO S(LT_QUOT) // "
|
||||
#define LT_PIPE S(LT_BSLS) // |
|
||||
// Row 4
|
||||
@@ -120,9 +120,9 @@
|
||||
* │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ │ │ │ = │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ │ │ € │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
@@ -137,7 +137,7 @@
|
||||
#define LT_6 ALGR(LT_SCAR) // 6
|
||||
#define LT_7 ALGR(LT_UOGO) // 7
|
||||
#define LT_8 ALGR(LT_UMAC) // 8
|
||||
#define LT_EQL ALGR(LT_PLUS) // =
|
||||
#define LT_EQL ALGR(LT_ZCAR) // =
|
||||
// Row 2
|
||||
#define LT_EURO ALGR(LT_E) // €
|
||||
|
||||
@@ -146,9 +146,9 @@
|
||||
* │ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ │ │ │ + │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
@@ -163,4 +163,4 @@
|
||||
#define LT_CIRC S(ALGR(LT_SCAR)) // ^
|
||||
#define LT_AMPR S(ALGR(LT_UOGO)) // &
|
||||
#define LT_ASTR S(ALGR(LT_UMAC)) // *
|
||||
#define LT_PLUS S(ALGR(LT_PLUS)) // +
|
||||
#define LT_PLUS S(ALGR(LT_ZCAR)) // +
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ ; │ { │ } │ | │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ : │ { │ } │ | │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ " │ │
|
||||
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
|
||||
|
||||
@@ -114,8 +114,8 @@
|
||||
#define DV_QUES S(DV_QUOT) // ?
|
||||
#define DV_IQUE S(DV_IEXL) // ¿
|
||||
// Row 2
|
||||
#define DV_COLN S(KC_DOT) // :
|
||||
#define DV_SCLN S(KC_COMM) // ;
|
||||
#define DV_COLN S(DV_DOT) // :
|
||||
#define DV_SCLN S(DV_COMM) // ;
|
||||
#define DV_CIRC S(DV_GRV) // ^ (dead)
|
||||
#define DV_ASTR S(DV_PLUS) // *
|
||||
// Row 3
|
||||
|
||||
@@ -89,3 +89,31 @@ enum steno_combined_keycodes {
|
||||
STN_COMB_MAX = STN_EU,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef STENO_ENABLE_BOLT
|
||||
// TxBolt Codes
|
||||
# define TXB_NUL 0
|
||||
# define TXB_S_L 0b00000001
|
||||
# define TXB_T_L 0b00000010
|
||||
# define TXB_K_L 0b00000100
|
||||
# define TXB_P_L 0b00001000
|
||||
# define TXB_W_L 0b00010000
|
||||
# define TXB_H_L 0b00100000
|
||||
# define TXB_R_L 0b01000001
|
||||
# define TXB_A_L 0b01000010
|
||||
# define TXB_O_L 0b01000100
|
||||
# define TXB_STR 0b01001000
|
||||
# define TXB_E_R 0b01010000
|
||||
# define TXB_U_R 0b01100000
|
||||
# define TXB_F_R 0b10000001
|
||||
# define TXB_R_R 0b10000010
|
||||
# define TXB_P_R 0b10000100
|
||||
# define TXB_B_R 0b10001000
|
||||
# define TXB_L_R 0b10010000
|
||||
# define TXB_G_R 0b10100000
|
||||
# define TXB_T_R 0b11000001
|
||||
# define TXB_S_R 0b11000010
|
||||
# define TXB_D_R 0b11000100
|
||||
# define TXB_Z_R 0b11001000
|
||||
# define TXB_NUM 0b11010000
|
||||
#endif // STENO_ENABLE_BOLT
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
#define TR_CURR S(ALGR(TR_4)) // ¤
|
||||
#define TR_IQUE S(ALGR(TR_SLSH)) // ¿
|
||||
// Row 2
|
||||
#define TR_REGD S(ALGR(TR_I) // ®
|
||||
#define TR_REGD S(ALGR(TR_I)) // ®
|
||||
// Row 3
|
||||
#define TR_SECT S(ALGR(TR_IDOT)) // §
|
||||
#define TR_FORD S(ALGR(TR_A)) // ª
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
#define US_CURR ALGR(US_4) // ¤
|
||||
#define US_EURO ALGR(US_5) // €
|
||||
#define US_DCIR ALGR(US_6) // ^ (dead)
|
||||
#define US_HORN ALGR(US_7) // ̛̛ (dead)
|
||||
#define US_HORN ALGR(US_7) // ̛ (dead)
|
||||
#define US_OGON ALGR(US_8) // ˛ (dead)
|
||||
#define US_LSQU ALGR(US_9) // ‘
|
||||
#define US_RSQU ALGR(US_0) // ’
|
||||
|
||||
32
quantum/keymap_introspection.c
Normal file
32
quantum/keymap_introspection.c
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// Pull the actual keymap code so that we can inspect stuff from it
|
||||
#include KEYMAP_C
|
||||
|
||||
// Allow for keymap or userspace rules.mk to specify an alternate location for the keymap array
|
||||
#ifdef INTROSPECTION_KEYMAP_C
|
||||
# include INTROSPECTION_KEYMAP_C
|
||||
#endif // INTROSPECTION_KEYMAP_C
|
||||
|
||||
#include "keymap_introspection.h"
|
||||
|
||||
#define NUM_KEYMAP_LAYERS ((uint8_t)(sizeof(keymaps) / ((MATRIX_ROWS) * (MATRIX_COLS) * sizeof(uint16_t))))
|
||||
|
||||
uint8_t keymap_layer_count(void) {
|
||||
return NUM_KEYMAP_LAYERS;
|
||||
}
|
||||
|
||||
_Static_assert(NUM_KEYMAP_LAYERS <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT");
|
||||
|
||||
#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
|
||||
|
||||
# define NUM_ENCODERMAP_LAYERS ((uint8_t)(sizeof(encoder_map) / ((NUM_ENCODERS) * (2) * sizeof(uint16_t))))
|
||||
|
||||
uint8_t encodermap_layer_count(void) {
|
||||
return NUM_ENCODERMAP_LAYERS;
|
||||
}
|
||||
|
||||
_Static_assert(NUM_KEYMAP_LAYERS == NUM_ENCODERMAP_LAYERS, "Number of encoder_map layers doesn't match the number of keymap layers");
|
||||
|
||||
#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
|
||||
15
quantum/keymap_introspection.h
Normal file
15
quantum/keymap_introspection.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Get the number of layers defined in the keymap
|
||||
uint8_t keymap_layer_count(void);
|
||||
|
||||
#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
|
||||
|
||||
// Get the number of layers defined in the encoder map
|
||||
uint8_t encodermap_layer_count(void);
|
||||
|
||||
#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "led.h"
|
||||
#include "host.h"
|
||||
#include "timer.h"
|
||||
#include "debug.h"
|
||||
#include "gpio.h"
|
||||
|
||||
@@ -54,6 +55,14 @@ static void handle_backlight_caps_lock(led_t led_state) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t last_led_modification_time = 0;
|
||||
uint32_t last_led_activity_time(void) {
|
||||
return last_led_modification_time;
|
||||
}
|
||||
uint32_t last_led_activity_elapsed(void) {
|
||||
return timer_elapsed32(last_led_modification_time);
|
||||
}
|
||||
|
||||
/** \brief Lock LED set callback - keymap/user level
|
||||
*
|
||||
* \deprecated Use led_update_user() instead.
|
||||
@@ -174,7 +183,8 @@ void led_task(void) {
|
||||
// update LED
|
||||
uint8_t led_status = host_keyboard_leds();
|
||||
if (last_led_status != led_status) {
|
||||
last_led_status = led_status;
|
||||
last_led_status = led_status;
|
||||
last_led_modification_time = timer_read32();
|
||||
|
||||
if (debug_keyboard) {
|
||||
debug("led_task: ");
|
||||
|
||||
@@ -61,6 +61,9 @@ void led_set_kb(uint8_t usb_led);
|
||||
bool led_update_user(led_t led_state);
|
||||
bool led_update_kb(led_t led_state);
|
||||
|
||||
uint32_t last_led_activity_time(void); // Timestamp of the LED activity
|
||||
uint32_t last_led_activity_elapsed(void); // Number of milliseconds since the last LED activity
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -618,10 +618,20 @@ void led_matrix_decrease_speed(void) {
|
||||
led_matrix_decrease_speed_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_set_flags_eeprom_helper(led_flags_t flags, bool write_to_eeprom) {
|
||||
led_matrix_eeconfig.flags = flags;
|
||||
eeconfig_flag_led_matrix(write_to_eeprom);
|
||||
dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.flags);
|
||||
}
|
||||
|
||||
led_flags_t led_matrix_get_flags(void) {
|
||||
return led_matrix_eeconfig.flags;
|
||||
}
|
||||
|
||||
void led_matrix_set_flags(led_flags_t flags) {
|
||||
led_matrix_eeconfig.flags = flags;
|
||||
led_matrix_set_flags_eeprom_helper(flags, true);
|
||||
}
|
||||
|
||||
void led_matrix_set_flags_noeeprom(led_flags_t flags) {
|
||||
led_matrix_set_flags_eeprom_helper(flags, false);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#ifdef IS31FL3733
|
||||
# include "is31fl3733-simple.h"
|
||||
#endif
|
||||
#ifdef CKLED2001
|
||||
# include "ckled2001-simple.h"
|
||||
#endif
|
||||
|
||||
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
|
||||
# define LED_MATRIX_LED_FLUSH_LIMIT 16
|
||||
@@ -158,6 +161,7 @@ void led_matrix_decrease_speed(void);
|
||||
void led_matrix_decrease_speed_noeeprom(void);
|
||||
led_flags_t led_matrix_get_flags(void);
|
||||
void led_matrix_set_flags(led_flags_t flags);
|
||||
void led_matrix_set_flags_noeeprom(led_flags_t flags);
|
||||
|
||||
typedef struct {
|
||||
/* Perform any initialisation required for the other driver functions to work. */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* in their own files.
|
||||
*/
|
||||
|
||||
#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FLCOMMON)
|
||||
#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FLCOMMON) || defined(CKLED2001)
|
||||
# include "i2c_master.h"
|
||||
|
||||
static void init(void) {
|
||||
@@ -78,6 +78,22 @@ static void init(void) {
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(CKLED2001)
|
||||
# if defined(LED_DRIVER_SHUTDOWN_PIN)
|
||||
setPinOutput(LED_DRIVER_SHUTDOWN_PIN);
|
||||
writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
|
||||
# endif
|
||||
|
||||
CKLED2001_init(DRIVER_ADDR_1);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
CKLED2001_init(DRIVER_ADDR_2);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
CKLED2001_init(DRIVER_ADDR_3);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
CKLED2001_init(DRIVER_ADDR_4);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
|
||||
@@ -87,6 +103,8 @@ static void init(void) {
|
||||
IS31FL3733_set_led_control_register(index, true);
|
||||
# elif defined(IS31FLCOMMON)
|
||||
IS31FL_simple_set_scaling_buffer(index, true);
|
||||
# elif defined(CKLED2001)
|
||||
CKLED2001_set_led_control_register(index, true);
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -129,6 +147,17 @@ static void init(void) {
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(CKLED2001)
|
||||
CKLED2001_update_led_control_registers(DRIVER_ADDR_1, 0);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
CKLED2001_update_led_control_registers(DRIVER_ADDR_2, 1);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
CKLED2001_update_led_control_registers(DRIVER_ADDR_3, 2);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
CKLED2001_update_led_control_registers(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -194,5 +223,25 @@ const led_matrix_driver_t led_matrix_driver = {
|
||||
.set_value = IS31FL_simple_set_brightness,
|
||||
.set_value_all = IS31FL_simple_set_brigntness_all,
|
||||
};
|
||||
# elif defined(CKLED2001)
|
||||
static void flush(void) {
|
||||
CKLED2001_update_pwm_buffers(DRIVER_ADDR_1, 0);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
CKLED2001_update_pwm_buffers(DRIVER_ADDR_2, 1);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
CKLED2001_update_pwm_buffers(DRIVER_ADDR_3, 2);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
CKLED2001_update_pwm_buffers(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
const led_matrix_driver_t led_matrix_driver = {
|
||||
.init = init,
|
||||
.flush = flush,
|
||||
.set_value = CKLED2001_set_value,
|
||||
.set_value_all = CKLED2001_set_value_all,
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,6 @@ void print_set_sendchar(sendchar_func_t send) {
|
||||
func = send;
|
||||
}
|
||||
|
||||
void _putchar(char character) {
|
||||
void putchar_(char character) {
|
||||
func(character);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,22 @@
|
||||
|
||||
void print_set_sendchar(sendchar_func_t func);
|
||||
|
||||
/**
|
||||
* @brief This macro suppress format warnings for the function that is passed
|
||||
* in. The main use-case is that `b` format specifier for printing binary
|
||||
* numbers is not in the official C standard. Inclusion is planned for the
|
||||
* upcoming C2X C standard, but until then GCC will always output a warning for
|
||||
* a unknown format specifier.
|
||||
*/
|
||||
#define IGNORE_FORMAT_WARNING(func) \
|
||||
do { \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wformat\""); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wformat-extra-args\""); \
|
||||
func; \
|
||||
_Pragma("GCC diagnostic pop"); \
|
||||
} while (0)
|
||||
|
||||
#ifndef NO_PRINT
|
||||
# if __has_include_next("_print.h")
|
||||
# include_next "_print.h" /* Include the platforms print.h */
|
||||
@@ -78,25 +94,25 @@ void print_set_sendchar(sendchar_func_t func);
|
||||
#define print_hex16(i) xprintf("%04X", i)
|
||||
#define print_hex32(i) xprintf("%08lX", i)
|
||||
/* binary */
|
||||
#define print_bin4(i) xprintf("%04b", i)
|
||||
#define print_bin8(i) xprintf("%08b", i)
|
||||
#define print_bin16(i) xprintf("%016b", i)
|
||||
#define print_bin32(i) xprintf("%032lb", i)
|
||||
#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
|
||||
#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
|
||||
#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
|
||||
#define print_bin4(i) IGNORE_FORMAT_WARNING(xprintf("%04b", i))
|
||||
#define print_bin8(i) IGNORE_FORMAT_WARNING(xprintf("%08b", i))
|
||||
#define print_bin16(i) IGNORE_FORMAT_WARNING(xprintf("%016b", i))
|
||||
#define print_bin32(i) IGNORE_FORMAT_WARNING(xprintf("%032lb", i))
|
||||
#define print_bin_reverse8(i) IGNORE_FORMAT_WARNING(xprintf("%08b", bitrev(i)))
|
||||
#define print_bin_reverse16(i) IGNORE_FORMAT_WARNING(xprintf("%016b", bitrev16(i)))
|
||||
#define print_bin_reverse32(i) IGNORE_FORMAT_WARNING(xprintf("%032lb", bitrev32(i)))
|
||||
/* print value utility */
|
||||
#define print_val_dec(v) xprintf(#v ": %u\n", v)
|
||||
#define print_val_decs(v) xprintf(#v ": %d\n", v)
|
||||
#define print_val_hex8(v) xprintf(#v ": %X\n", v)
|
||||
#define print_val_hex16(v) xprintf(#v ": %02X\n", v)
|
||||
#define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
|
||||
#define print_val_bin8(v) xprintf(#v ": %08b\n", v)
|
||||
#define print_val_bin16(v) xprintf(#v ": %016b\n", v)
|
||||
#define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
|
||||
#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
|
||||
#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
|
||||
#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
|
||||
#define print_val_bin8(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %08b\n", v))
|
||||
#define print_val_bin16(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %016b\n", v))
|
||||
#define print_val_bin32(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %032lb\n", v))
|
||||
#define print_val_bin_reverse8(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %08b\n", bitrev(v)))
|
||||
#define print_val_bin_reverse16(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %016b\n", bitrev16(v)))
|
||||
#define print_val_bin_reverse32(v) IGNORE_FORMAT_WARNING(xprintf(#v ": %032lb\n", bitrev32(v)))
|
||||
|
||||
// User print disables the normal print messages in the body of QMK/TMK code and
|
||||
// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do
|
||||
@@ -114,22 +130,22 @@ void print_set_sendchar(sendchar_func_t func);
|
||||
#define uprint_hex16(i) uprintf("%04X", i)
|
||||
#define uprint_hex32(i) uprintf("%08lX", i)
|
||||
/* binary */
|
||||
#define uprint_bin4(i) uprintf("%04b", i)
|
||||
#define uprint_bin8(i) uprintf("%08b", i)
|
||||
#define uprint_bin16(i) uprintf("%016b", i)
|
||||
#define uprint_bin32(i) uprintf("%032lb", i)
|
||||
#define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i))
|
||||
#define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i))
|
||||
#define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i))
|
||||
#define uprint_bin4(i) IGNORE_FORMAT_WARNING(uprintf("%04b", i))
|
||||
#define uprint_bin8(i) IGNORE_FORMAT_WARNING(uprintf("%08b", i))
|
||||
#define uprint_bin16(i) IGNORE_FORMAT_WARNING(uprintf("%016b", i))
|
||||
#define uprint_bin32(i) IGNORE_FORMAT_WARNING(uprintf("%032lb", i))
|
||||
#define uprint_bin_reverse8(i) IGNORE_FORMAT_WARNING(uprintf("%08b", bitrev(i)))
|
||||
#define uprint_bin_reverse16(i) IGNORE_FORMAT_WARNING(uprintf("%016b", bitrev16(i)))
|
||||
#define uprint_bin_reverse32(i) IGNORE_FORMAT_WARNING(uprintf("%032lb", bitrev32(i)))
|
||||
/* print value utility */
|
||||
#define uprint_val_dec(v) uprintf(#v ": %u\n", v)
|
||||
#define uprint_val_decs(v) uprintf(#v ": %d\n", v)
|
||||
#define uprint_val_hex8(v) uprintf(#v ": %X\n", v)
|
||||
#define uprint_val_hex16(v) uprintf(#v ": %02X\n", v)
|
||||
#define uprint_val_hex32(v) uprintf(#v ": %04lX\n", v)
|
||||
#define uprint_val_bin8(v) uprintf(#v ": %08b\n", v)
|
||||
#define uprint_val_bin16(v) uprintf(#v ": %016b\n", v)
|
||||
#define uprint_val_bin32(v) uprintf(#v ": %032lb\n", v)
|
||||
#define uprint_val_bin_reverse8(v) uprintf(#v ": %08b\n", bitrev(v))
|
||||
#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v))
|
||||
#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v))
|
||||
#define uprint_val_bin8(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %08b\n", v))
|
||||
#define uprint_val_bin16(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %016b\n", v))
|
||||
#define uprint_val_bin32(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %032lb\n", v))
|
||||
#define uprint_val_bin_reverse8(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %08b\n", bitrev(v)))
|
||||
#define uprint_val_bin_reverse16(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %016b\n", bitrev16(v)))
|
||||
#define uprint_val_bin_reverse32(v) IGNORE_FORMAT_WARNING(uprintf(#v ": %032lb\n", bitrev32(v)))
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
PRINTF_PATH = $(LIB_PATH)/printf
|
||||
PRINTF_PATH = $(LIB_PATH)/printf/src
|
||||
|
||||
VPATH += $(PRINTF_PATH)
|
||||
SRC += $(PRINTF_PATH)/printf.c
|
||||
VPATH += $(PRINTF_PATH) $(PRINTF_PATH)/printf
|
||||
SRC += printf.c
|
||||
QUANTUM_SRC +=$(QUANTUM_DIR)/logging/print.c
|
||||
OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT
|
||||
OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL
|
||||
OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG
|
||||
OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T
|
||||
|
||||
OPT_DEFS += -DPRINTF_SUPPORT_DECIMAL_SPECIFIERS=0
|
||||
OPT_DEFS += -DPRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS=0
|
||||
OPT_DEFS += -DPRINTF_SUPPORT_LONG_LONG=0
|
||||
OPT_DEFS += -DPRINTF_SUPPORT_WRITEBACK_SPECIFIER=0
|
||||
OPT_DEFS += -DSUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS=0
|
||||
OPT_DEFS += -DPRINTF_ALIAS_STANDARD_FUNCTION_NAMES=1
|
||||
|
||||
@@ -337,10 +337,9 @@ uint8_t matrix_scan(void) {
|
||||
if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
|
||||
changed = (changed || matrix_post_scan());
|
||||
changed = debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed) | matrix_post_scan();
|
||||
#else
|
||||
debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
|
||||
changed = debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
|
||||
matrix_scan_quantum();
|
||||
#endif
|
||||
return (uint8_t)changed;
|
||||
|
||||
@@ -122,7 +122,7 @@ bool matrix_post_scan(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
|
||||
/* `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);
|
||||
}
|
||||
@@ -169,10 +169,9 @@ __attribute__((weak)) uint8_t matrix_scan(void) {
|
||||
bool changed = matrix_scan_custom(raw_matrix);
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
|
||||
changed = (changed || matrix_post_scan());
|
||||
changed = debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed) | matrix_post_scan();
|
||||
#else
|
||||
debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
|
||||
changed = debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
|
||||
matrix_scan_quantum();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -67,11 +67,18 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
|
||||
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
|
||||
uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;
|
||||
/* milliseconds between repeated motion events (0-255) */
|
||||
uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
|
||||
# ifdef MK_KINETIC_SPEED
|
||||
float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
|
||||
# else
|
||||
uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
|
||||
# endif
|
||||
uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
|
||||
uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
|
||||
|
||||
# ifndef MK_COMBINED
|
||||
# ifndef MK_KINETIC_SPEED
|
||||
|
||||
/* Default accelerated mode */
|
||||
|
||||
static uint8_t move_unit(void) {
|
||||
uint16_t unit;
|
||||
@@ -109,8 +116,7 @@ static uint8_t wheel_unit(void) {
|
||||
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
|
||||
}
|
||||
|
||||
# else /* #ifndef MK_COMBINED */
|
||||
# ifdef MK_KINETIC_SPEED
|
||||
# else /* #ifndef MK_KINETIC_SPEED */
|
||||
|
||||
/*
|
||||
* Kinetic movement acceleration algorithm
|
||||
@@ -148,27 +154,27 @@ static uint8_t move_unit(void) {
|
||||
return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed;
|
||||
}
|
||||
|
||||
float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
|
||||
|
||||
static uint8_t wheel_unit(void) {
|
||||
float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
|
||||
|
||||
if (mousekey_accel & ((1 << 0) | (1 << 2))) {
|
||||
speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS;
|
||||
} else if (mousekey_repeat && mouse_timer) {
|
||||
} else if (mousekey_wheel_repeat && mouse_timer) {
|
||||
if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) {
|
||||
const float time_elapsed = timer_elapsed(mouse_timer) / 50;
|
||||
speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed;
|
||||
}
|
||||
speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;
|
||||
}
|
||||
|
||||
mk_wheel_interval = 1000.0f / speed;
|
||||
|
||||
return 1;
|
||||
return (uint8_t)speed > MOUSEKEY_WHEEL_INITIAL_MOVEMENTS ? 2 : 1;
|
||||
}
|
||||
|
||||
# else /* #ifndef MK_KINETIC_SPEED */
|
||||
# endif /* #ifndef MK_KINETIC_SPEED */
|
||||
# else /* #ifndef MK_COMBINED */
|
||||
|
||||
/* Combined mode */
|
||||
|
||||
static uint8_t move_unit(void) {
|
||||
uint16_t unit;
|
||||
@@ -206,8 +212,7 @@ static uint8_t wheel_unit(void) {
|
||||
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
|
||||
}
|
||||
|
||||
# endif /* #ifndef MK_KINETIC_SPEED */
|
||||
# endif /* #ifndef MK_COMBINED */
|
||||
# endif /* #ifndef MK_COMBINED */
|
||||
|
||||
void mousekey_task(void) {
|
||||
// report cursor and scroll movement independently
|
||||
|
||||
@@ -39,7 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ifndef MK_KINETIC_SPEED
|
||||
# define MOUSEKEY_MOVE_DELTA 8
|
||||
# else
|
||||
# define MOUSEKEY_MOVE_DELTA 5
|
||||
# define MOUSEKEY_MOVE_DELTA 16
|
||||
# endif
|
||||
# endif
|
||||
# ifndef MOUSEKEY_WHEEL_DELTA
|
||||
@@ -82,7 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# define MOUSEKEY_INITIAL_SPEED 100
|
||||
# endif
|
||||
# ifndef MOUSEKEY_BASE_SPEED
|
||||
# define MOUSEKEY_BASE_SPEED 1000
|
||||
# define MOUSEKEY_BASE_SPEED 5000
|
||||
# endif
|
||||
# ifndef MOUSEKEY_DECELERATED_SPEED
|
||||
# define MOUSEKEY_DECELERATED_SPEED 400
|
||||
|
||||
@@ -440,10 +440,18 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
|
||||
# include "qp_ili9341.h"
|
||||
#endif // QUANTUM_PAINTER_ILI9341_ENABLE
|
||||
|
||||
#ifdef QUANTUM_PAINTER_ILI9488_ENABLE
|
||||
# include "qp_ili9488.h"
|
||||
#endif // QUANTUM_PAINTER_ILI9488_ENABLE
|
||||
|
||||
#ifdef QUANTUM_PAINTER_ST7789_ENABLE
|
||||
# include "qp_st7789.h"
|
||||
#endif // QUANTUM_PAINTER_ST7789_ENABLE
|
||||
|
||||
#ifdef QUANTUM_PAINTER_ST7735_ENABLE
|
||||
# include "qp_st7735.h"
|
||||
#endif // QUANTUM_PAINTER_ST7735_ENABLE
|
||||
|
||||
#ifdef QUANTUM_PAINTER_GC9A01_ENABLE
|
||||
# include "qp_gc9a01.h"
|
||||
#endif // QUANTUM_PAINTER_GC9A01_ENABLE
|
||||
|
||||
@@ -3,7 +3,7 @@ QUANTUM_PAINTER_DRIVERS ?=
|
||||
QUANTUM_PAINTER_ANIMATIONS_ENABLE ?= yes
|
||||
|
||||
# The list of permissible drivers that can be listed in QUANTUM_PAINTER_DRIVERS
|
||||
VALID_QUANTUM_PAINTER_DRIVERS := ili9163_spi ili9341_spi st7789_spi gc9a01_spi ssd1351_spi
|
||||
VALID_QUANTUM_PAINTER_DRIVERS := ili9163_spi ili9341_spi ili9488_spi st7789_spi st7735_spi gc9a01_spi ssd1351_spi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -61,6 +61,17 @@ define handle_quantum_painter_driver
|
||||
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
|
||||
$(DRIVER_PATH)/painter/ili9xxx/qp_ili9341.c \
|
||||
|
||||
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9488_spi)
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
|
||||
OPT_DEFS += -DQUANTUM_PAINTER_ILI9488_ENABLE -DQUANTUM_PAINTER_ILI9488_SPI_ENABLE
|
||||
COMMON_VPATH += \
|
||||
$(DRIVER_PATH)/painter/tft_panel \
|
||||
$(DRIVER_PATH)/painter/ili9xxx
|
||||
SRC += \
|
||||
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
|
||||
$(DRIVER_PATH)/painter/ili9xxx/qp_ili9488.c \
|
||||
|
||||
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),st7789_spi)
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
|
||||
@@ -72,6 +83,17 @@ define handle_quantum_painter_driver
|
||||
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
|
||||
$(DRIVER_PATH)/painter/st77xx/qp_st7789.c
|
||||
|
||||
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),st7735_spi)
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
|
||||
OPT_DEFS += -DQUANTUM_PAINTER_ST7735_ENABLE -DQUANTUM_PAINTER_ST7735_SPI_ENABLE
|
||||
COMMON_VPATH += \
|
||||
$(DRIVER_PATH)/painter/tft_panel \
|
||||
$(DRIVER_PATH)/painter/st77xx
|
||||
SRC += \
|
||||
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
|
||||
$(DRIVER_PATH)/painter/st77xx/qp_st7735.c
|
||||
|
||||
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),gc9a01_spi)
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
|
||||
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
#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(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT) || defined(POINTING_DEVICE_COMBINED)
|
||||
# ifndef SPLIT_POINTING_ENABLE
|
||||
# error "Using POINTING_DEVICE_LEFT or POINTING_DEVICE_RIGHT or POINTING_DEVICE_COMBINED, then SPLIT_POINTING_ENABLE is required but has not been defined"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
# include "transactions.h"
|
||||
# include "keyboard.h"
|
||||
@@ -132,14 +139,15 @@ __attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bo
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_init(void) {
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
if (!(POINTING_DEVICE_THIS_SIDE)) {
|
||||
return;
|
||||
}
|
||||
if ((POINTING_DEVICE_THIS_SIDE))
|
||||
#endif
|
||||
pointing_device_driver.init();
|
||||
{
|
||||
pointing_device_driver.init();
|
||||
#ifdef POINTING_DEVICE_MOTION_PIN
|
||||
setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
|
||||
setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
pointing_device_init_kb();
|
||||
pointing_device_init_user();
|
||||
}
|
||||
@@ -177,7 +185,8 @@ __attribute__((weak)) void pointing_device_send(void) {
|
||||
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 = mouse_report.x, y = mouse_report.y;
|
||||
mouse_xy_report_t x = mouse_report.x;
|
||||
mouse_xy_report_t y = mouse_report.y;
|
||||
# if defined(POINTING_DEVICE_ROTATION_90)
|
||||
mouse_report.x = y;
|
||||
mouse_report.y = -x;
|
||||
@@ -347,7 +356,7 @@ void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
|
||||
* @param[in] int16_t value
|
||||
* @return int8_t clamped value
|
||||
*/
|
||||
static inline int8_t pointing_device_movement_clamp(int16_t value) {
|
||||
static inline int8_t pointing_device_hv_clamp(int16_t value) {
|
||||
if (value < INT8_MIN) {
|
||||
return INT8_MIN;
|
||||
} else if (value > INT8_MAX) {
|
||||
@@ -357,6 +366,21 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clamps int16_t to int8_t
|
||||
*
|
||||
* @param[in] clamp_range_t value
|
||||
* @return mouse_xy_report_t clamped value
|
||||
*/
|
||||
static inline mouse_xy_report_t pointing_device_xy_clamp(clamp_range_t value) {
|
||||
if (value < XY_REPORT_MIN) {
|
||||
return XY_REPORT_MIN;
|
||||
} else if (value > XY_REPORT_MAX) {
|
||||
return XY_REPORT_MAX;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief combines 2 mouse reports and returns 2
|
||||
*
|
||||
@@ -369,10 +393,10 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) {
|
||||
* @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.x = pointing_device_xy_clamp((clamp_range_t)left_report.x + right_report.x);
|
||||
left_report.y = pointing_device_xy_clamp((clamp_range_t)left_report.y + right_report.y);
|
||||
left_report.h = pointing_device_hv_clamp((int16_t)left_report.h + right_report.h);
|
||||
left_report.v = pointing_device_hv_clamp((int16_t)left_report.v + right_report.v);
|
||||
left_report.buttons |= right_report.buttons;
|
||||
return left_report;
|
||||
}
|
||||
@@ -389,8 +413,9 @@ report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, repor
|
||||
*/
|
||||
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) || defined(POINTING_DEVICE_ROTATION_180_RIGHT) || defined(POINTING_DEVICE_ROTATION_270_RIGHT)
|
||||
mouse_xy_report_t x = mouse_report.x;
|
||||
mouse_xy_report_t y = mouse_report.y;
|
||||
# if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
|
||||
mouse_report.x = y;
|
||||
mouse_report.y = -x;
|
||||
@@ -31,6 +31,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# include "drivers/sensors/analog_joystick.h"
|
||||
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
|
||||
# include "drivers/sensors/cirque_pinnacle.h"
|
||||
# include "drivers/sensors/cirque_pinnacle_gestures.h"
|
||||
# include "pointing_device_gestures.h"
|
||||
#elif defined(POINTING_DEVICE_DRIVER_paw3204)
|
||||
# include "drivers/sensors/paw3204.h"
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
|
||||
# include "i2c_master.h"
|
||||
# include "drivers/sensors/pimoroni_trackball.h"
|
||||
@@ -44,12 +48,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ifdef PIMORONI_TRACKBALL_ROTATE
|
||||
# define POINTING_DEVICE_ROTATION_90
|
||||
# endif
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3360) || defined(POINTING_DEVICE_DRIVER_pmw3389)
|
||||
# include "spi_master.h"
|
||||
# include "drivers/sensors/pmw3360.h"
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3389)
|
||||
# include "spi_master.h"
|
||||
# include "drivers/sensors/pmw3389.h"
|
||||
# include "drivers/sensors/pmw33xx_common.h"
|
||||
#else
|
||||
void pointing_device_driver_init(void);
|
||||
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
|
||||
@@ -75,6 +76,16 @@ typedef enum {
|
||||
POINTING_DEVICE_BUTTON8,
|
||||
} pointing_device_buttons_t;
|
||||
|
||||
#ifdef MOUSE_EXTENDED_REPORT
|
||||
# define XY_REPORT_MIN INT16_MIN
|
||||
# define XY_REPORT_MAX INT16_MAX
|
||||
typedef int32_t clamp_range_t;
|
||||
#else
|
||||
# define XY_REPORT_MIN INT8_MIN
|
||||
# define XY_REPORT_MAX INT8_MAX
|
||||
typedef int16_t clamp_range_t;
|
||||
#endif
|
||||
|
||||
void pointing_device_init(void);
|
||||
void pointing_device_task(void);
|
||||
void pointing_device_send(void);
|
||||
368
quantum/pointing_device/pointing_device_drivers.c
Normal file
368
quantum/pointing_device/pointing_device_drivers.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
|
||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
* Copyright 2021 Dasky (@daskygit)
|
||||
*
|
||||
* 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 "pointing_device.h"
|
||||
#include "debug.h"
|
||||
#include "wait.h"
|
||||
#include "timer.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#define CONSTRAIN_HID(amt) ((amt) < INT8_MIN ? INT8_MIN : ((amt) > INT8_MAX ? INT8_MAX : (amt)))
|
||||
#define CONSTRAIN_HID_XY(amt) ((amt) < XY_REPORT_MIN ? XY_REPORT_MIN : ((amt) > XY_REPORT_MAX ? XY_REPORT_MAX : (amt)))
|
||||
|
||||
// get_report functions should probably be moved to their respective drivers.
|
||||
|
||||
#if defined(POINTING_DEVICE_DRIVER_adns5050)
|
||||
report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
|
||||
report_adns5050_t data = adns5050_read_burst();
|
||||
|
||||
if (data.dx != 0 || data.dy != 0) {
|
||||
# ifdef CONSOLE_ENABLE
|
||||
if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
|
||||
# endif
|
||||
|
||||
mouse_report.x = (mouse_xy_report_t)data.dx;
|
||||
mouse_report.y = (mouse_xy_report_t)data.dy;
|
||||
}
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = adns5050_init,
|
||||
.get_report = adns5050_get_report,
|
||||
.set_cpi = adns5050_set_cpi,
|
||||
.get_cpi = adns5050_get_cpi,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_adns9800)
|
||||
|
||||
report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
|
||||
report_adns9800_t sensor_report = adns9800_get_report();
|
||||
|
||||
mouse_report.x = CONSTRAIN_HID_XY(sensor_report.x);
|
||||
mouse_report.y = CONSTRAIN_HID_XY(sensor_report.y);
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = adns9800_init,
|
||||
.get_report = adns9800_get_report_driver,
|
||||
.set_cpi = adns9800_set_cpi,
|
||||
.get_cpi = adns9800_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
|
||||
report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
|
||||
report_analog_joystick_t data = analog_joystick_read();
|
||||
|
||||
# ifdef CONSOLE_ENABLE
|
||||
if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
|
||||
# endif
|
||||
|
||||
mouse_report.x = data.x;
|
||||
mouse_report.y = data.y;
|
||||
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = analog_joystick_init,
|
||||
.get_report = analog_joystick_get_report,
|
||||
.set_cpi = NULL,
|
||||
.get_cpi = NULL
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
|
||||
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
static bool cursor_glide_enable = true;
|
||||
|
||||
static cursor_glide_context_t glide = {.config = {
|
||||
.coef = 102, /* Good default friction coef */
|
||||
.interval = 10, /* 100sps */
|
||||
.trigger_px = 10, /* Default threshold in case of hover, set to 0 if you'd like */
|
||||
}};
|
||||
|
||||
void cirque_pinnacle_enable_cursor_glide(bool enable) {
|
||||
cursor_glide_enable = enable;
|
||||
}
|
||||
|
||||
void cirque_pinnacle_configure_cursor_glide(float trigger_px) {
|
||||
glide.config.trigger_px = trigger_px;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if CIRQUE_PINNACLE_POSITION_MODE
|
||||
report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
|
||||
pinnacle_data_t touchData = cirque_pinnacle_read_data();
|
||||
mouse_xy_report_t report_x = 0, report_y = 0;
|
||||
static uint16_t x = 0, y = 0;
|
||||
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
cursor_glide_t glide_report = {0};
|
||||
|
||||
if (cursor_glide_enable) {
|
||||
glide_report = cursor_glide_check(&glide);
|
||||
}
|
||||
# endif
|
||||
|
||||
if (!touchData.valid) {
|
||||
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
if (cursor_glide_enable && glide_report.valid) {
|
||||
report_x = glide_report.dx;
|
||||
report_y = glide_report.dy;
|
||||
goto mouse_report_update;
|
||||
}
|
||||
# endif
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
# if CONSOLE_ENABLE
|
||||
if (debug_mouse && touchData.touchDown) {
|
||||
dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue);
|
||||
}
|
||||
# endif
|
||||
|
||||
// Scale coordinates to arbitrary X, Y resolution
|
||||
cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale());
|
||||
|
||||
if (!cirque_pinnacle_gestures(&mouse_report, touchData)) {
|
||||
if (x && y && touchData.xValue && touchData.yValue) {
|
||||
report_x = CONSTRAIN_HID_XY((int16_t)(touchData.xValue - x));
|
||||
report_y = CONSTRAIN_HID_XY((int16_t)(touchData.yValue - y));
|
||||
}
|
||||
x = touchData.xValue;
|
||||
y = touchData.yValue;
|
||||
|
||||
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
if (cursor_glide_enable) {
|
||||
if (touchData.touchDown) {
|
||||
cursor_glide_update(&glide, report_x, report_y, touchData.zValue);
|
||||
} else if (!glide_report.valid) {
|
||||
glide_report = cursor_glide_start(&glide);
|
||||
if (glide_report.valid) {
|
||||
report_x = glide_report.dx;
|
||||
report_y = glide_report.dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
mouse_report_update:
|
||||
# endif
|
||||
mouse_report.x = report_x;
|
||||
mouse_report.y = report_y;
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
uint16_t cirque_pinnacle_get_cpi(void) {
|
||||
return CIRQUE_PINNACLE_PX_TO_INCH(cirque_pinnacle_get_scale());
|
||||
}
|
||||
void cirque_pinnacle_set_cpi(uint16_t cpi) {
|
||||
cirque_pinnacle_set_scale(CIRQUE_PINNACLE_INCH_TO_PX(cpi));
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = cirque_pinnacle_init,
|
||||
.get_report = cirque_pinnacle_get_report,
|
||||
.set_cpi = cirque_pinnacle_set_cpi,
|
||||
.get_cpi = cirque_pinnacle_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
# else
|
||||
report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
|
||||
pinnacle_data_t touchData = cirque_pinnacle_read_data();
|
||||
|
||||
// Scale coordinates to arbitrary X, Y resolution
|
||||
cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale());
|
||||
|
||||
if (touchData.valid) {
|
||||
mouse_report.buttons = touchData.buttons;
|
||||
mouse_report.x = CONSTRAIN_HID_XY(touchData.xDelta);
|
||||
mouse_report.y = CONSTRAIN_HID_XY(touchData.yDelta);
|
||||
mouse_report.v = touchData.wheelCount;
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = cirque_pinnacle_init,
|
||||
.get_report = cirque_pinnacle_get_report,
|
||||
.set_cpi = cirque_pinnacle_set_scale,
|
||||
.get_cpi = cirque_pinnacle_get_scale
|
||||
};
|
||||
// clang-format on
|
||||
# endif
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_paw3204)
|
||||
|
||||
report_mouse_t paw3204_get_report(report_mouse_t mouse_report) {
|
||||
report_paw3204_t data = paw3204_read();
|
||||
if (data.isMotion) {
|
||||
# ifdef CONSOLE_ENABLE
|
||||
dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
|
||||
# endif
|
||||
|
||||
mouse_report.x = data.x;
|
||||
mouse_report.y = data.y;
|
||||
}
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = paw3204_init,
|
||||
.get_report = paw3204_get_report,
|
||||
.set_cpi = paw3204_set_cpi,
|
||||
.get_cpi = paw3204_get_cpi,
|
||||
};
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
|
||||
|
||||
mouse_xy_report_t pimoroni_trackball_adapt_values(clamp_range_t* offset) {
|
||||
if (*offset > XY_REPORT_MAX) {
|
||||
*offset -= XY_REPORT_MAX;
|
||||
return (mouse_xy_report_t)XY_REPORT_MAX;
|
||||
} else if (*offset < XY_REPORT_MIN) {
|
||||
*offset += XY_REPORT_MAX;
|
||||
return (mouse_xy_report_t)XY_REPORT_MIN;
|
||||
} else {
|
||||
mouse_xy_report_t temp_return = *offset;
|
||||
*offset = 0;
|
||||
return temp_return;
|
||||
}
|
||||
}
|
||||
|
||||
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 clamp_range_t x_offset = 0, y_offset = 0;
|
||||
|
||||
if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
|
||||
i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
|
||||
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
error_count = 0;
|
||||
|
||||
if (!(pimoroni_data.click & 128)) {
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
|
||||
if (!debounce) {
|
||||
x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
|
||||
y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
|
||||
mouse_report.x = pimoroni_trackball_adapt_values(&x_offset);
|
||||
mouse_report.y = pimoroni_trackball_adapt_values(&y_offset);
|
||||
} else {
|
||||
debounce--;
|
||||
}
|
||||
} else {
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
|
||||
debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
|
||||
}
|
||||
} else {
|
||||
error_count++;
|
||||
}
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.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) || defined(POINTING_DEVICE_DRIVER_pmw3389)
|
||||
static void pmw33xx_init_wrapper(void) {
|
||||
pmw33xx_init(0);
|
||||
}
|
||||
|
||||
static void pmw33xx_set_cpi_wrapper(uint16_t cpi) {
|
||||
pmw33xx_set_cpi(0, cpi);
|
||||
}
|
||||
|
||||
static uint16_t pmw33xx_get_cpi_wrapper(void) {
|
||||
return pmw33xx_get_cpi(0);
|
||||
}
|
||||
|
||||
report_mouse_t pmw33xx_get_report(report_mouse_t mouse_report) {
|
||||
pmw33xx_report_t report = pmw33xx_read_burst(0);
|
||||
static bool in_motion = false;
|
||||
|
||||
if (report.motion.b.is_lifted) {
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
if (!report.motion.b.is_motion) {
|
||||
in_motion = false;
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
if (!in_motion) {
|
||||
in_motion = true;
|
||||
dprintf("PWM3360 (0): starting motion\n");
|
||||
}
|
||||
|
||||
mouse_report.x = CONSTRAIN_HID_XY(report.delta_x);
|
||||
mouse_report.y = CONSTRAIN_HID_XY(report.delta_y);
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = pmw33xx_init_wrapper,
|
||||
.get_report = pmw33xx_get_report,
|
||||
.set_cpi = pmw33xx_set_cpi_wrapper,
|
||||
.get_cpi = pmw33xx_get_cpi_wrapper
|
||||
};
|
||||
// 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;
|
||||
}
|
||||
__attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) {
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = pointing_device_driver_init,
|
||||
.get_report = pointing_device_driver_get_report,
|
||||
.get_cpi = pointing_device_driver_get_cpi,
|
||||
.set_cpi = pointing_device_driver_set_cpi
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
133
quantum/pointing_device/pointing_device_gestures.c
Normal file
133
quantum/pointing_device/pointing_device_gestures.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* Copyright 2022 Daniel Kao <daniel.m.kao@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 <string.h>
|
||||
#include "pointing_device_gestures.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
# ifdef POINTING_DEVICE_MOTION_PIN
|
||||
# error POINTING_DEVICE_MOTION_PIN not supported when using inertial cursor. Need repeated calls to get_report() to generate glide events.
|
||||
# endif
|
||||
|
||||
static void cursor_glide_stop(cursor_glide_context_t* glide) {
|
||||
memset(&glide->status, 0, sizeof(glide->status));
|
||||
}
|
||||
|
||||
static cursor_glide_t cursor_glide(cursor_glide_context_t* glide) {
|
||||
cursor_glide_status_t* status = &glide->status;
|
||||
cursor_glide_t report;
|
||||
int32_t p;
|
||||
int32_t x, y;
|
||||
|
||||
if (status->v0 == 0) {
|
||||
report.dx = 0;
|
||||
report.dy = 0;
|
||||
report.valid = false;
|
||||
cursor_glide_stop(glide);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status->counter++;
|
||||
/* Calculate current 1D position */
|
||||
p = status->v0 * status->counter - (int32_t)glide->config.coef * status->counter * status->counter / 2;
|
||||
/*
|
||||
* Translate to x & y axes
|
||||
* Done this way instead of applying friction to each axis separately, so we don't end up with the shorter axis stuck at 0 towards the end of diagonal movements.
|
||||
*/
|
||||
x = (int32_t)(p * status->dx0 / status->v0);
|
||||
y = (int32_t)(p * status->dy0 / status->v0);
|
||||
report.dx = (mouse_xy_report_t)(x - status->x);
|
||||
report.dy = (mouse_xy_report_t)(y - status->y);
|
||||
report.valid = true;
|
||||
if (report.dx <= 1 && report.dx >= -1 && report.dy <= 1 && report.dy >= -1) {
|
||||
/* Stop gliding once speed is low enough */
|
||||
cursor_glide_stop(glide);
|
||||
goto exit;
|
||||
}
|
||||
status->x = x;
|
||||
status->y = y;
|
||||
status->timer = timer_read();
|
||||
|
||||
exit:
|
||||
return report;
|
||||
}
|
||||
|
||||
cursor_glide_t cursor_glide_check(cursor_glide_context_t* glide) {
|
||||
cursor_glide_t invalid_report = {0, 0, false};
|
||||
cursor_glide_status_t* status = &glide->status;
|
||||
|
||||
if (status->z || (status->dx0 == 0 && status->dy0 == 0) || timer_elapsed(status->timer) < glide->config.interval) {
|
||||
return invalid_report;
|
||||
} else {
|
||||
return cursor_glide(glide);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t sqrt32(uint32_t x) {
|
||||
uint32_t l, m, h;
|
||||
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
} else if (x > (UINT16_MAX >> 2)) {
|
||||
/* Safe upper bound to avoid integer overflow with m * m */
|
||||
h = UINT16_MAX;
|
||||
} else {
|
||||
/* Upper bound based on closest log2 */
|
||||
h = (1 << (((__builtin_clzl(1) - __builtin_clzl(x) + 1) + 1) >> 1));
|
||||
}
|
||||
/* Lower bound based on closest log2 */
|
||||
l = (1 << ((__builtin_clzl(1) - __builtin_clzl(x)) >> 1));
|
||||
|
||||
/* Binary search to find integer square root */
|
||||
while (l != h - 1) {
|
||||
m = (l + h) / 2;
|
||||
if (m * m <= x) {
|
||||
l = m;
|
||||
} else {
|
||||
h = m;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
cursor_glide_t cursor_glide_start(cursor_glide_context_t* glide) {
|
||||
cursor_glide_t invalid_report = {0, 0, false};
|
||||
cursor_glide_status_t* status = &glide->status;
|
||||
|
||||
status->timer = timer_read();
|
||||
status->counter = 0;
|
||||
status->v0 = (status->dx0 == 0 && status->dy0 == 0) ? 0.0 : sqrt32(((int32_t)status->dx0 * 256 * status->dx0 * 256) + ((int32_t)status->dy0 * 256 * status->dy0 * 256)); // skip trigonometry if not needed, calculate distance in Q8
|
||||
status->x = 0;
|
||||
status->y = 0;
|
||||
status->z = 0;
|
||||
|
||||
if (status->v0 < ((uint32_t)glide->config.trigger_px * 256)) { /* Q8 comparison */
|
||||
/* Not enough velocity to be worth gliding, abort */
|
||||
cursor_glide_stop(glide);
|
||||
return invalid_report;
|
||||
}
|
||||
|
||||
return cursor_glide(glide);
|
||||
}
|
||||
|
||||
void cursor_glide_update(cursor_glide_context_t* glide, mouse_xy_report_t dx, mouse_xy_report_t dy, uint16_t z) {
|
||||
cursor_glide_status_t* status = &glide->status;
|
||||
|
||||
status->dx0 = dx;
|
||||
status->dy0 = dy;
|
||||
status->z = z;
|
||||
}
|
||||
#endif
|
||||
58
quantum/pointing_device/pointing_device_gestures.h
Normal file
58
quantum/pointing_device/pointing_device_gestures.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* Copyright 2022 Daniel Kao <daniel.m.kao@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "report.h"
|
||||
|
||||
#ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
|
||||
typedef struct {
|
||||
mouse_xy_report_t dx;
|
||||
mouse_xy_report_t dy;
|
||||
bool valid;
|
||||
} cursor_glide_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t trigger_px; /* Pixels of movement needed to trigger cursor glide */
|
||||
uint16_t coef; /* Coefficient of friction */
|
||||
uint16_t interval; /* Glide report interval, in milliseconds */
|
||||
} cursor_glide_config_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t v0;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint16_t z;
|
||||
uint16_t timer;
|
||||
uint16_t counter;
|
||||
mouse_xy_report_t dx0;
|
||||
mouse_xy_report_t dy0;
|
||||
} cursor_glide_status_t;
|
||||
|
||||
typedef struct {
|
||||
cursor_glide_config_t config;
|
||||
cursor_glide_status_t status;
|
||||
} cursor_glide_context_t;
|
||||
|
||||
/* Check glide report conditions, calculates glide coordinates */
|
||||
cursor_glide_t cursor_glide_check(cursor_glide_context_t* glide);
|
||||
|
||||
/* Start glide reporting, gives first set of glide coordinates */
|
||||
cursor_glide_t cursor_glide_start(cursor_glide_context_t* glide);
|
||||
|
||||
/* Update glide engine on the latest cursor movement, cursor glide is based on the final movement */
|
||||
void cursor_glide_update(cursor_glide_context_t* glide, mouse_xy_report_t dx, mouse_xy_report_t dy, uint16_t z);
|
||||
#endif
|
||||
@@ -1,295 +0,0 @@
|
||||
/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
|
||||
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
* Copyright 2021 Dasky (@daskygit)
|
||||
*
|
||||
* 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 "pointing_device.h"
|
||||
#include "debug.h"
|
||||
#include "wait.h"
|
||||
#include "timer.h"
|
||||
#include <stddef.h>
|
||||
|
||||
// hid mouse reports cannot exceed -127 to 127, so constrain to that value
|
||||
#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
|
||||
|
||||
// get_report functions should probably be moved to their respective drivers.
|
||||
#if defined(POINTING_DEVICE_DRIVER_adns5050)
|
||||
report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
|
||||
report_adns5050_t data = adns5050_read_burst();
|
||||
|
||||
if (data.dx != 0 || data.dy != 0) {
|
||||
# ifdef CONSOLE_ENABLE
|
||||
if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
|
||||
# endif
|
||||
|
||||
mouse_report.x = data.dx;
|
||||
mouse_report.y = data.dy;
|
||||
}
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = adns5050_init,
|
||||
.get_report = adns5050_get_report,
|
||||
.set_cpi = adns5050_set_cpi,
|
||||
.get_cpi = adns5050_get_cpi,
|
||||
};
|
||||
// clang-format on
|
||||
#elif defined(POINTING_DEVICE_DRIVER_adns9800)
|
||||
|
||||
report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
|
||||
report_adns9800_t sensor_report = adns9800_get_report();
|
||||
|
||||
int8_t clamped_x = constrain_hid(sensor_report.x);
|
||||
int8_t clamped_y = constrain_hid(sensor_report.y);
|
||||
|
||||
mouse_report.x = clamped_x;
|
||||
mouse_report.y = clamped_y;
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = adns9800_init,
|
||||
.get_report = adns9800_get_report_driver,
|
||||
.set_cpi = adns9800_set_cpi,
|
||||
.get_cpi = adns9800_get_cpi
|
||||
};
|
||||
// clang-format on
|
||||
#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
|
||||
report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
|
||||
report_analog_joystick_t data = analog_joystick_read();
|
||||
|
||||
# ifdef CONSOLE_ENABLE
|
||||
if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
|
||||
# endif
|
||||
|
||||
mouse_report.x = data.x;
|
||||
mouse_report.y = data.y;
|
||||
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = analog_joystick_init,
|
||||
.get_report = analog_joystick_get_report,
|
||||
.set_cpi = NULL,
|
||||
.get_cpi = NULL
|
||||
};
|
||||
// clang-format on
|
||||
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
|
||||
# ifndef CIRQUE_PINNACLE_TAPPING_TERM
|
||||
# include "action.h"
|
||||
# include "action_tapping.h"
|
||||
# define CIRQUE_PINNACLE_TAPPING_TERM GET_TAPPING_TERM(KC_BTN1, &(keyrecord_t){})
|
||||
# endif
|
||||
# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
|
||||
# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)
|
||||
# endif
|
||||
|
||||
report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
|
||||
pinnacle_data_t touchData = cirque_pinnacle_read_data();
|
||||
static uint16_t x = 0, y = 0, mouse_timer = 0;
|
||||
int8_t report_x = 0, report_y = 0;
|
||||
static bool is_z_down = false;
|
||||
|
||||
cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution
|
||||
|
||||
if (x && y && touchData.xValue && touchData.yValue) {
|
||||
report_x = (int8_t)(touchData.xValue - x);
|
||||
report_y = (int8_t)(touchData.yValue - y);
|
||||
}
|
||||
x = touchData.xValue;
|
||||
y = touchData.yValue;
|
||||
|
||||
if ((bool)touchData.zValue != is_z_down) {
|
||||
is_z_down = (bool)touchData.zValue;
|
||||
if (!touchData.zValue) {
|
||||
if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) {
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
|
||||
pointing_device_set_report(mouse_report);
|
||||
pointing_device_send();
|
||||
# if TAP_CODE_DELAY > 0
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
# endif
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
|
||||
pointing_device_set_report(mouse_report);
|
||||
pointing_device_send();
|
||||
}
|
||||
}
|
||||
mouse_timer = timer_read();
|
||||
}
|
||||
if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) {
|
||||
mouse_timer = 0;
|
||||
}
|
||||
mouse_report.x = report_x;
|
||||
mouse_report.y = report_y;
|
||||
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = cirque_pinnacle_init,
|
||||
.get_report = cirque_pinnacle_get_report,
|
||||
.set_cpi = cirque_pinnacle_set_scale,
|
||||
.get_cpi = cirque_pinnacle_get_scale
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
|
||||
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) {
|
||||
i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
|
||||
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
error_count = 0;
|
||||
|
||||
if (!(pimoroni_data.click & 128)) {
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
|
||||
if (!debounce) {
|
||||
x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
|
||||
y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
|
||||
pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset);
|
||||
pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset);
|
||||
} else {
|
||||
debounce--;
|
||||
}
|
||||
} else {
|
||||
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
|
||||
debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
|
||||
}
|
||||
} else {
|
||||
error_count++;
|
||||
}
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.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 pmw3360_device_init(void) {
|
||||
pmw3360_init(0);
|
||||
}
|
||||
|
||||
report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
|
||||
report_pmw3360_t data = pmw3360_read_burst(0);
|
||||
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 = 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;
|
||||
}
|
||||
__attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) {
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {}
|
||||
|
||||
// clang-format off
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = pointing_device_driver_init,
|
||||
.get_report = pointing_device_driver_get_report,
|
||||
.get_cpi = pointing_device_driver_get_cpi,
|
||||
.set_cpi = pointing_device_driver_set_cpi
|
||||
};
|
||||
// clang-format on
|
||||
#endif
|
||||
@@ -124,7 +124,12 @@ bool get_autoshift_shift_state(uint16_t keycode) {
|
||||
/** \brief Restores the shift key if it was cancelled by Auto Shift */
|
||||
static void autoshift_flush_shift(void) {
|
||||
autoshift_flags.holding_shift = false;
|
||||
del_weak_mods(MOD_BIT(KC_LSFT));
|
||||
# ifdef CAPS_WORD_ENABLE
|
||||
if (!is_caps_word_on())
|
||||
# endif // CAPS_WORD_ENABLE
|
||||
{
|
||||
del_weak_mods(MOD_BIT(KC_LSFT));
|
||||
}
|
||||
if (autoshift_flags.cancelling_lshift) {
|
||||
autoshift_flags.cancelling_lshift = false;
|
||||
add_mods(MOD_BIT(KC_LSFT));
|
||||
@@ -326,11 +331,13 @@ void autoshift_disable(void) {
|
||||
|
||||
# ifndef AUTO_SHIFT_NO_SETUP
|
||||
void autoshift_timer_report(void) {
|
||||
# ifdef SEND_STRING_ENABLE
|
||||
char display[8];
|
||||
|
||||
snprintf(display, 8, "\n%d\n", autoshift_timeout);
|
||||
|
||||
send_string((const char *)display);
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define AUTO_SHIFT_SPECIAL \
|
||||
KC_TAB: \
|
||||
case KC_MINUS ... KC_SLASH: \
|
||||
case KC_NONUS_BSLASH
|
||||
case KC_NONUS_BACKSLASH
|
||||
// clang-format on
|
||||
|
||||
bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
@@ -101,14 +101,34 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
return true;
|
||||
|
||||
#ifndef NO_ACTION_TAPPING
|
||||
// Corresponding to mod keys above, a held mod-tap is handled as:
|
||||
// * For shift mods, pass KC_LSFT or KC_RSFT to
|
||||
// caps_word_press_user() to determine whether to continue.
|
||||
// * For Shift + AltGr (MOD_RSFT | MOD_RALT), pass RSFT(KC_RALT).
|
||||
// * AltGr (MOD_RALT) is ignored.
|
||||
// * Otherwise stop Caps Word.
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
|
||||
if (record->tap.count == 0) {
|
||||
// Deactivate if a mod becomes active through holding
|
||||
// a mod-tap key.
|
||||
caps_word_off();
|
||||
return true;
|
||||
if (record->tap.count == 0) { // Mod-tap key is held.
|
||||
const uint8_t mods = (keycode >> 8) & 0x1f;
|
||||
switch (mods) {
|
||||
case MOD_LSFT:
|
||||
keycode = KC_LSFT;
|
||||
break;
|
||||
case MOD_RSFT:
|
||||
keycode = KC_RSFT;
|
||||
break;
|
||||
case MOD_RSFT | MOD_RALT:
|
||||
keycode = RSFT(KC_RALT);
|
||||
break;
|
||||
case MOD_RALT:
|
||||
return true;
|
||||
default:
|
||||
caps_word_off();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
keycode &= 0xff;
|
||||
}
|
||||
keycode &= 0xff;
|
||||
break;
|
||||
|
||||
# ifndef NO_ACTION_LAYER
|
||||
@@ -131,7 +151,11 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
#endif // SWAP_HANDS_ENABLE
|
||||
}
|
||||
|
||||
#ifdef AUTO_SHIFT_ENABLE
|
||||
del_weak_mods(get_autoshift_state() ? ~MOD_BIT(KC_LSFT) : 0xff);
|
||||
#else
|
||||
clear_weak_mods();
|
||||
#endif // AUTO_SHIFT_ENABLE
|
||||
if (caps_word_press_user(keycode)) {
|
||||
send_keyboard_report();
|
||||
return true;
|
||||
|
||||
@@ -234,7 +234,16 @@ static inline void dump_key_buffer(void) {
|
||||
#endif
|
||||
}
|
||||
record->event.time = 0;
|
||||
|
||||
#if defined(CAPS_WORD_ENABLE) && defined(AUTO_SHIFT_ENABLE)
|
||||
// Edge case: preserve the weak Left Shift mod if both Caps Word and
|
||||
// Auto Shift are on. Caps Word capitalizes by setting the weak Left
|
||||
// Shift mod during the press event, but Auto Shift doesn't send the
|
||||
// key until it receives the release event.
|
||||
del_weak_mods((is_caps_word_on() && get_autoshift_state()) ? ~MOD_BIT(KC_LSFT) : 0xff);
|
||||
#else
|
||||
clear_weak_mods();
|
||||
#endif // defined(CAPS_WORD_ENABLE) && defined(AUTO_SHIFT_ENABLE)
|
||||
|
||||
#if TAP_CODE_DELAY > 0
|
||||
// only delay once and for a non-tapping key
|
||||
|
||||
@@ -86,6 +86,9 @@ void dynamic_macro_play(keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_
|
||||
while (macro_buffer != macro_end) {
|
||||
process_record(macro_buffer);
|
||||
macro_buffer += direction;
|
||||
#ifdef DYNAMIC_MACRO_DELAY
|
||||
wait_ms(DYNAMIC_MACRO_DELAY);
|
||||
#endif
|
||||
}
|
||||
|
||||
clear_keyboard();
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
#endif
|
||||
|
||||
static void tapping_term_report(void) {
|
||||
#ifdef SEND_STRING_ENABLE
|
||||
const char *tapping_term_str = get_u16_str(g_tapping_term, ' ');
|
||||
// Skip padding spaces
|
||||
while (*tapping_term_str == ' ') {
|
||||
tapping_term_str++;
|
||||
}
|
||||
send_string(tapping_term_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
@@ -106,7 +106,7 @@ bool process_joystick_analogread_quantum() {
|
||||
|
||||
wait_us(10);
|
||||
|
||||
# if defined(__AVR__) || defined(PROTOCOL_CHIBIOS)
|
||||
# if defined(ANALOG_JOYSTICK_ENABLE) && (defined(__AVR__) || defined(PROTOCOL_CHIBIOS))
|
||||
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
|
||||
# else
|
||||
// default to resting position
|
||||
|
||||
@@ -64,6 +64,7 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {
|
||||
} else {
|
||||
leading = false;
|
||||
leader_end();
|
||||
return true;
|
||||
}
|
||||
# ifdef LEADER_PER_KEY_TIMING
|
||||
leader_time = timer_read();
|
||||
|
||||
@@ -45,12 +45,16 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
||||
case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT:
|
||||
case MAGIC_TOGGLE_GUI:
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
case MAGIC_SWAP_ESCAPE_CAPSLOCK ... MAGIC_TOGGLE_ESCAPE_CAPSLOCK:
|
||||
/* keymap config */
|
||||
keymap_config.raw = eeconfig_read_keymap();
|
||||
switch (keycode) {
|
||||
case MAGIC_SWAP_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = true;
|
||||
break;
|
||||
case MAGIC_SWAP_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = true;
|
||||
break;
|
||||
case MAGIC_CAPSLOCK_TO_CONTROL:
|
||||
keymap_config.capslock_to_control = true;
|
||||
break;
|
||||
@@ -94,6 +98,9 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
||||
case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = false;
|
||||
break;
|
||||
case MAGIC_UNCAPSLOCK_TO_CONTROL:
|
||||
keymap_config.capslock_to_control = false;
|
||||
break;
|
||||
@@ -172,6 +179,9 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
|
||||
break;
|
||||
case MAGIC_TOGGLE_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = !keymap_config.swap_escape_capslock;
|
||||
break;
|
||||
}
|
||||
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2017 Joseph Wasson
|
||||
/* Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
|
||||
*
|
||||
* 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
|
||||
@@ -15,77 +15,118 @@
|
||||
*/
|
||||
#include "process_steno.h"
|
||||
#include "quantum_keycodes.h"
|
||||
#include "eeprom.h"
|
||||
#include "keymap_steno.h"
|
||||
#include "virtser.h"
|
||||
#include <string.h>
|
||||
#ifdef VIRTSER_ENABLE
|
||||
# include "virtser.h"
|
||||
#endif
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
# include "eeprom.h"
|
||||
#endif
|
||||
|
||||
// TxBolt Codes
|
||||
#define TXB_NUL 0
|
||||
#define TXB_S_L 0b00000001
|
||||
#define TXB_T_L 0b00000010
|
||||
#define TXB_K_L 0b00000100
|
||||
#define TXB_P_L 0b00001000
|
||||
#define TXB_W_L 0b00010000
|
||||
#define TXB_H_L 0b00100000
|
||||
#define TXB_R_L 0b01000001
|
||||
#define TXB_A_L 0b01000010
|
||||
#define TXB_O_L 0b01000100
|
||||
#define TXB_STR 0b01001000
|
||||
#define TXB_E_R 0b01010000
|
||||
#define TXB_U_R 0b01100000
|
||||
#define TXB_F_R 0b10000001
|
||||
#define TXB_R_R 0b10000010
|
||||
#define TXB_P_R 0b10000100
|
||||
#define TXB_B_R 0b10001000
|
||||
#define TXB_L_R 0b10010000
|
||||
#define TXB_G_R 0b10100000
|
||||
#define TXB_T_R 0b11000001
|
||||
#define TXB_S_R 0b11000010
|
||||
#define TXB_D_R 0b11000100
|
||||
#define TXB_Z_R 0b11001000
|
||||
#define TXB_NUM 0b11010000
|
||||
// All steno keys that have been pressed to form this chord,
|
||||
// stored in MAX_STROKE_SIZE groups of 8-bit arrays.
|
||||
static uint8_t chord[MAX_STROKE_SIZE] = {0};
|
||||
// The number of physical keys actually being held down.
|
||||
// This is not always equal to the number of 1 bits in `chord` because it is possible to
|
||||
// simultaneously press down four keys, then release three of those four keys and then press yet
|
||||
// another key while the fourth finger is still holding down its key.
|
||||
// At the end of this scenario given as an example, `chord` would have five bits set to 1 but
|
||||
// `n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down.
|
||||
static int8_t n_pressed_keys = 0;
|
||||
|
||||
#define TXB_GRP0 0b00000000
|
||||
#define TXB_GRP1 0b01000000
|
||||
#define TXB_GRP2 0b10000000
|
||||
#define TXB_GRP3 0b11000000
|
||||
#define TXB_GRPMASK 0b11000000
|
||||
|
||||
#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
|
||||
|
||||
#define BOLT_STATE_SIZE 4
|
||||
#define GEMINI_STATE_SIZE 6
|
||||
#define MAX_STATE_SIZE GEMINI_STATE_SIZE
|
||||
|
||||
static uint8_t state[MAX_STATE_SIZE] = {0};
|
||||
static uint8_t chord[MAX_STATE_SIZE] = {0};
|
||||
static int8_t pressed = 0;
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
static steno_mode_t mode;
|
||||
#elif defined(STENO_ENABLE_GEMINI)
|
||||
static const steno_mode_t mode = STENO_MODE_GEMINI;
|
||||
#elif defined(STENO_ENABLE_BOLT)
|
||||
static const steno_mode_t mode = STENO_MODE_BOLT;
|
||||
#endif
|
||||
|
||||
static inline void steno_clear_chord(void) {
|
||||
memset(chord, 0, sizeof(chord));
|
||||
}
|
||||
|
||||
#ifdef STENO_ENABLE_GEMINI
|
||||
|
||||
# ifdef VIRTSER_ENABLE
|
||||
void send_steno_chord_gemini(void) {
|
||||
// Set MSB to 1 to indicate the start of packet
|
||||
chord[0] |= 0x80;
|
||||
for (uint8_t i = 0; i < GEMINI_STROKE_SIZE; ++i) {
|
||||
virtser_send(chord[i]);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# pragma message "VIRTSER_ENABLE = yes is required for Gemini PR to work properly out of the box!"
|
||||
# endif // VIRTSER_ENABLE
|
||||
|
||||
/**
|
||||
* @precondition: `key` is pressed
|
||||
*/
|
||||
bool add_gemini_key_to_chord(uint8_t key) {
|
||||
// Although each group of the packet is 8 bits long, the MSB is reserved
|
||||
// to indicate whether that byte is the first byte of the packet (MSB=1)
|
||||
// or one of the remaining five bytes of the packet (MSB=0).
|
||||
// As a consequence, only 7 out of the 8 bits are left to be used as a bit array
|
||||
// for the steno keys of that group.
|
||||
const int group_idx = key / 7;
|
||||
const int intra_group_idx = key - group_idx * 7;
|
||||
// The 0th steno key of the group has bit=0b01000000, the 1st has bit=0b00100000, etc.
|
||||
const uint8_t bit = 1 << (6 - intra_group_idx);
|
||||
chord[group_idx] |= bit;
|
||||
return false;
|
||||
}
|
||||
#endif // STENO_ENABLE_GEMINI
|
||||
|
||||
#ifdef STENO_ENABLE_BOLT
|
||||
|
||||
# define TXB_GRP0 0b00000000
|
||||
# define TXB_GRP1 0b01000000
|
||||
# define TXB_GRP2 0b10000000
|
||||
# define TXB_GRP3 0b11000000
|
||||
# define TXB_GRPMASK 0b11000000
|
||||
|
||||
# define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
|
||||
|
||||
static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
|
||||
|
||||
# ifdef VIRTSER_ENABLE
|
||||
static void send_steno_chord_bolt(void) {
|
||||
for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) {
|
||||
// TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys.
|
||||
// If a user chorded the keys of the first group with keys of the last group, for example, there
|
||||
// would be bytes of 0x00 in `chord` for the middle groups which we mustn't send.
|
||||
if (chord[i]) {
|
||||
virtser_send(chord[i]);
|
||||
}
|
||||
}
|
||||
// Sending a null packet is not always necessary, but it is simpler and more reliable
|
||||
// to unconditionally send it every time instead of keeping track of more states and
|
||||
// creating more branches in the execution of the program.
|
||||
virtser_send(0);
|
||||
}
|
||||
# else
|
||||
# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!"
|
||||
# endif // VIRTSER_ENABLE
|
||||
|
||||
/**
|
||||
* @precondition: `key` is pressed
|
||||
*/
|
||||
static bool add_bolt_key_to_chord(uint8_t key) {
|
||||
uint8_t boltcode = pgm_read_byte(boltmap + key);
|
||||
chord[TXB_GET_GROUP(boltcode)] |= boltcode;
|
||||
return false;
|
||||
}
|
||||
#endif // STENO_ENABLE_BOLT
|
||||
|
||||
#ifdef STENO_COMBINEDMAP
|
||||
/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
|
||||
static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
|
||||
static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
|
||||
#endif
|
||||
|
||||
static void steno_clear_state(void) {
|
||||
memset(state, 0, sizeof(state));
|
||||
memset(chord, 0, sizeof(chord));
|
||||
}
|
||||
|
||||
static void send_steno_state(uint8_t size, bool send_empty) {
|
||||
for (uint8_t i = 0; i < size; ++i) {
|
||||
if (chord[i] || send_empty) {
|
||||
#ifdef VIRTSER_ENABLE
|
||||
virtser_send(chord[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
void steno_init() {
|
||||
if (!eeconfig_is_enabled()) {
|
||||
eeconfig_init();
|
||||
@@ -94,19 +135,20 @@ void steno_init() {
|
||||
}
|
||||
|
||||
void steno_set_mode(steno_mode_t new_mode) {
|
||||
steno_clear_state();
|
||||
steno_clear_chord();
|
||||
mode = new_mode;
|
||||
eeprom_update_byte(EECONFIG_STENOMODE, mode);
|
||||
}
|
||||
#endif // STENO_ENABLE_ALL
|
||||
|
||||
/* override to intercept chords right before they get sent.
|
||||
* return zero to suppress normal sending behavior.
|
||||
*/
|
||||
__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) {
|
||||
__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) {
|
||||
__attribute__((weak)) bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -114,108 +156,94 @@ __attribute__((weak)) bool process_steno_user(uint16_t keycode, keyrecord_t *rec
|
||||
return true;
|
||||
}
|
||||
|
||||
static void send_steno_chord(void) {
|
||||
if (send_steno_chord_user(mode, chord)) {
|
||||
switch (mode) {
|
||||
case STENO_MODE_BOLT:
|
||||
send_steno_state(BOLT_STATE_SIZE, false);
|
||||
#ifdef VIRTSER_ENABLE
|
||||
virtser_send(0); // terminating byte
|
||||
#endif
|
||||
break;
|
||||
case STENO_MODE_GEMINI:
|
||||
chord[0] |= 0x80; // Indicate start of packet
|
||||
send_steno_state(GEMINI_STATE_SIZE, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
steno_clear_state();
|
||||
}
|
||||
|
||||
uint8_t *steno_get_state(void) {
|
||||
return &state[0];
|
||||
}
|
||||
|
||||
uint8_t *steno_get_chord(void) {
|
||||
return &chord[0];
|
||||
}
|
||||
|
||||
static bool update_state_bolt(uint8_t key, bool press) {
|
||||
uint8_t boltcode = pgm_read_byte(boltmap + key);
|
||||
if (press) {
|
||||
state[TXB_GET_GROUP(boltcode)] |= boltcode;
|
||||
chord[TXB_GET_GROUP(boltcode)] |= boltcode;
|
||||
} else {
|
||||
state[TXB_GET_GROUP(boltcode)] &= ~boltcode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool update_state_gemini(uint8_t key, bool press) {
|
||||
int idx = key / 7;
|
||||
uint8_t bit = 1 << (6 - (key % 7));
|
||||
if (press) {
|
||||
state[idx] |= bit;
|
||||
chord[idx] |= bit;
|
||||
} else {
|
||||
state[idx] &= ~bit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool process_steno(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode < QK_STENO || keycode > QK_STENO_MAX) {
|
||||
return true; // Not a steno key, pass it further along the chain
|
||||
/*
|
||||
* Clearing or sending the chord state is not necessary as we intentionally ignore whatever
|
||||
* normal keyboard keys the user may have tapped while chording steno keys.
|
||||
*/
|
||||
}
|
||||
if (IS_NOEVENT(record->event)) {
|
||||
return true;
|
||||
}
|
||||
if (!process_steno_user(keycode, record)) {
|
||||
return false; // User fully processed the steno key themselves
|
||||
}
|
||||
switch (keycode) {
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
case QK_STENO_BOLT:
|
||||
if (!process_steno_user(keycode, record)) {
|
||||
return false;
|
||||
}
|
||||
if (IS_PRESSED(record->event)) {
|
||||
steno_set_mode(STENO_MODE_BOLT);
|
||||
}
|
||||
return false;
|
||||
|
||||
case QK_STENO_GEMINI:
|
||||
if (!process_steno_user(keycode, record)) {
|
||||
return false;
|
||||
}
|
||||
if (IS_PRESSED(record->event)) {
|
||||
steno_set_mode(STENO_MODE_GEMINI);
|
||||
}
|
||||
return false;
|
||||
#endif // STENO_ENABLE_ALL
|
||||
|
||||
#ifdef STENO_COMBINEDMAP
|
||||
case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
|
||||
uint8_t result;
|
||||
result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
|
||||
result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
|
||||
return result;
|
||||
bool first_result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
|
||||
bool second_result = process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
|
||||
return first_result && second_result;
|
||||
}
|
||||
#endif
|
||||
#endif // STENO_COMBINEDMAP
|
||||
case STN__MIN ... STN__MAX:
|
||||
if (!process_steno_user(keycode, record)) {
|
||||
return false;
|
||||
}
|
||||
switch (mode) {
|
||||
case STENO_MODE_BOLT:
|
||||
update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event));
|
||||
break;
|
||||
case STENO_MODE_GEMINI:
|
||||
update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event));
|
||||
break;
|
||||
}
|
||||
// allow postprocessing hooks
|
||||
if (postprocess_steno_user(keycode, record, mode, chord, pressed)) {
|
||||
if (IS_PRESSED(record->event)) {
|
||||
++pressed;
|
||||
} else {
|
||||
--pressed;
|
||||
if (pressed <= 0) {
|
||||
pressed = 0;
|
||||
send_steno_chord();
|
||||
}
|
||||
if (IS_PRESSED(record->event)) {
|
||||
n_pressed_keys++;
|
||||
switch (mode) {
|
||||
#ifdef STENO_ENABLE_BOLT
|
||||
case STENO_MODE_BOLT:
|
||||
add_bolt_key_to_chord(keycode - QK_STENO);
|
||||
break;
|
||||
#endif // STENO_ENABLE_BOLT
|
||||
#ifdef STENO_ENABLE_GEMINI
|
||||
case STENO_MODE_GEMINI:
|
||||
add_gemini_key_to_chord(keycode - QK_STENO);
|
||||
break;
|
||||
#endif // STENO_ENABLE_GEMINI
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (!post_process_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
|
||||
return false;
|
||||
}
|
||||
} else { // is released
|
||||
n_pressed_keys--;
|
||||
if (!post_process_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
|
||||
return false;
|
||||
}
|
||||
if (n_pressed_keys > 0) {
|
||||
// User hasn't released all keys yet,
|
||||
// so the chord cannot be sent
|
||||
return false;
|
||||
}
|
||||
n_pressed_keys = 0;
|
||||
if (!send_steno_chord_user(mode, chord)) {
|
||||
steno_clear_chord();
|
||||
return false;
|
||||
}
|
||||
switch (mode) {
|
||||
#if defined(STENO_ENABLE_BOLT) && defined(VIRTSER_ENABLE)
|
||||
case STENO_MODE_BOLT:
|
||||
send_steno_chord_bolt();
|
||||
break;
|
||||
#endif // STENO_ENABLE_BOLT && VIRTSER_ENABLE
|
||||
#if defined(STENO_ENABLE_GEMINI) && defined(VIRTSER_ENABLE)
|
||||
case STENO_MODE_GEMINI:
|
||||
send_steno_chord_gemini();
|
||||
break;
|
||||
#endif // STENO_ENABLE_GEMINI && VIRTSER_ENABLE
|
||||
default:
|
||||
break;
|
||||
}
|
||||
steno_clear_chord();
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,22 @@
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t;
|
||||
#define BOLT_STROKE_SIZE 4
|
||||
#define GEMINI_STROKE_SIZE 6
|
||||
|
||||
bool process_steno(uint16_t keycode, keyrecord_t *record);
|
||||
void steno_init(void);
|
||||
void steno_set_mode(steno_mode_t mode);
|
||||
uint8_t *steno_get_state(void);
|
||||
uint8_t *steno_get_chord(void);
|
||||
#ifdef STENO_ENABLE_GEMINI
|
||||
# define MAX_STROKE_SIZE GEMINI_STROKE_SIZE
|
||||
#else
|
||||
# define MAX_STROKE_SIZE BOLT_STROKE_SIZE
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
STENO_MODE_GEMINI,
|
||||
STENO_MODE_BOLT,
|
||||
} steno_mode_t;
|
||||
|
||||
bool process_steno(uint16_t keycode, keyrecord_t *record);
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
void steno_init(void);
|
||||
void steno_set_mode(steno_mode_t mode);
|
||||
#endif // STENO_ENABLE_ALL
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
#include "quantum.h"
|
||||
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
uint8_t get_oneshot_mods(void);
|
||||
#endif
|
||||
|
||||
static uint16_t last_td;
|
||||
static int16_t highest_td = -1;
|
||||
static uint16_t active_td;
|
||||
static uint16_t last_tap_time;
|
||||
|
||||
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
@@ -34,18 +30,14 @@ void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data)
|
||||
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
|
||||
if (state->count == 1) {
|
||||
register_code16(pair->kc1);
|
||||
} else if (state->count == 2) {
|
||||
register_code16(pair->kc2);
|
||||
}
|
||||
register_code16(pair->kc1);
|
||||
}
|
||||
|
||||
void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
if (state->count == 1) {
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
unregister_code16(pair->kc1);
|
||||
} else if (state->count == 2) {
|
||||
unregister_code16(pair->kc2);
|
||||
@@ -87,23 +79,40 @@ static inline void _process_tap_dance_action_fn(qk_tap_dance_state_t *state, voi
|
||||
}
|
||||
|
||||
static inline void process_tap_dance_action_on_each_tap(qk_tap_dance_action_t *action) {
|
||||
action->state.count++;
|
||||
action->state.weak_mods = get_mods();
|
||||
action->state.weak_mods |= get_weak_mods();
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
action->state.oneshot_mods = get_oneshot_mods();
|
||||
#endif
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap);
|
||||
}
|
||||
|
||||
void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
|
||||
if (action->state.finished) return;
|
||||
action->state.finished = true;
|
||||
add_mods(action->state.oneshot_mods);
|
||||
add_weak_mods(action->state.weak_mods);
|
||||
send_keyboard_report();
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished);
|
||||
}
|
||||
|
||||
static inline void process_tap_dance_action_on_reset(qk_tap_dance_action_t *action) {
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset);
|
||||
del_mods(action->state.oneshot_mods);
|
||||
del_weak_mods(action->state.weak_mods);
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
del_mods(action->state.oneshot_mods);
|
||||
#endif
|
||||
send_keyboard_report();
|
||||
action->state = (const qk_tap_dance_state_t){0};
|
||||
}
|
||||
|
||||
void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
|
||||
if (!action->state.finished) {
|
||||
action->state.finished = true;
|
||||
add_weak_mods(action->state.weak_mods);
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
add_mods(action->state.oneshot_mods);
|
||||
#endif
|
||||
send_keyboard_report();
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished);
|
||||
}
|
||||
active_td = 0;
|
||||
if (!action->state.pressed) {
|
||||
// There will not be a key release event, so reset now.
|
||||
process_tap_dance_action_on_reset(action);
|
||||
}
|
||||
}
|
||||
|
||||
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
@@ -111,51 +120,33 @@ void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
if (!record->event.pressed) return;
|
||||
|
||||
if (highest_td == -1) return;
|
||||
if (!active_td || keycode == active_td) return;
|
||||
|
||||
for (int i = 0; i <= highest_td; i++) {
|
||||
action = &tap_dance_actions[i];
|
||||
if (action->state.count) {
|
||||
if (keycode == action->state.keycode && keycode == last_td) continue;
|
||||
action->state.interrupted = true;
|
||||
action->state.interrupting_keycode = keycode;
|
||||
process_tap_dance_action_on_dance_finished(action);
|
||||
reset_tap_dance(&action->state);
|
||||
action = &tap_dance_actions[TD_INDEX(active_td)];
|
||||
action->state.interrupted = true;
|
||||
action->state.interrupting_keycode = keycode;
|
||||
process_tap_dance_action_on_dance_finished(action);
|
||||
|
||||
// Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with
|
||||
// modifiers), but these weak mods should not affect the keypress which interrupted the tap dance.
|
||||
clear_weak_mods();
|
||||
}
|
||||
}
|
||||
// Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with
|
||||
// modifiers), but these weak mods should not affect the keypress which interrupted the tap dance.
|
||||
clear_weak_mods();
|
||||
}
|
||||
|
||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
uint16_t idx = keycode - QK_TAP_DANCE;
|
||||
qk_tap_dance_action_t *action;
|
||||
|
||||
switch (keycode) {
|
||||
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
|
||||
if ((int16_t)idx > highest_td) highest_td = idx;
|
||||
action = &tap_dance_actions[idx];
|
||||
action = &tap_dance_actions[TD_INDEX(keycode)];
|
||||
|
||||
action->state.pressed = record->event.pressed;
|
||||
if (record->event.pressed) {
|
||||
action->state.keycode = keycode;
|
||||
action->state.count++;
|
||||
action->state.timer = timer_read();
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
action->state.oneshot_mods = get_oneshot_mods();
|
||||
#else
|
||||
action->state.oneshot_mods = 0;
|
||||
#endif
|
||||
action->state.weak_mods = get_mods();
|
||||
action->state.weak_mods |= get_weak_mods();
|
||||
last_tap_time = timer_read();
|
||||
process_tap_dance_action_on_each_tap(action);
|
||||
|
||||
last_td = keycode;
|
||||
active_td = action->state.finished ? 0 : keycode;
|
||||
} else {
|
||||
if (action->state.count && action->state.finished) {
|
||||
reset_tap_dance(&action->state);
|
||||
if (action->state.finished) {
|
||||
process_tap_dance_action_on_reset(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,35 +157,17 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
|
||||
void tap_dance_task() {
|
||||
if (highest_td == -1) return;
|
||||
uint16_t tap_user_defined;
|
||||
qk_tap_dance_action_t *action;
|
||||
|
||||
for (uint8_t i = 0; i <= highest_td; i++) {
|
||||
qk_tap_dance_action_t *action = &tap_dance_actions[i];
|
||||
if (action->custom_tapping_term > 0) {
|
||||
tap_user_defined = action->custom_tapping_term;
|
||||
} else {
|
||||
tap_user_defined = GET_TAPPING_TERM(action->state.keycode, &(keyrecord_t){});
|
||||
}
|
||||
if (action->state.count && timer_elapsed(action->state.timer) > tap_user_defined) {
|
||||
process_tap_dance_action_on_dance_finished(action);
|
||||
reset_tap_dance(&action->state);
|
||||
}
|
||||
if (!active_td || timer_elapsed(last_tap_time) <= GET_TAPPING_TERM(active_td, &(keyrecord_t){})) return;
|
||||
|
||||
action = &tap_dance_actions[TD_INDEX(active_td)];
|
||||
if (!action->state.interrupted) {
|
||||
process_tap_dance_action_on_dance_finished(action);
|
||||
}
|
||||
}
|
||||
|
||||
void reset_tap_dance(qk_tap_dance_state_t *state) {
|
||||
qk_tap_dance_action_t *action;
|
||||
|
||||
if (state->pressed) return;
|
||||
|
||||
action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
|
||||
|
||||
process_tap_dance_action_on_reset(action);
|
||||
|
||||
state->count = 0;
|
||||
state->interrupted = false;
|
||||
state->finished = false;
|
||||
state->interrupting_keycode = 0;
|
||||
last_td = 0;
|
||||
active_td = 0;
|
||||
process_tap_dance_action_on_reset((qk_tap_dance_action_t *)state);
|
||||
}
|
||||
|
||||
@@ -22,30 +22,27 @@
|
||||
# include <inttypes.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
uint8_t oneshot_mods;
|
||||
uint8_t weak_mods;
|
||||
uint16_t keycode;
|
||||
uint16_t interrupting_keycode;
|
||||
uint16_t timer;
|
||||
bool interrupted;
|
||||
bool pressed;
|
||||
bool finished;
|
||||
uint8_t count;
|
||||
uint8_t weak_mods;
|
||||
# ifndef NO_ACTION_ONESHOT
|
||||
uint8_t oneshot_mods;
|
||||
# endif
|
||||
bool pressed : 1;
|
||||
bool finished : 1;
|
||||
bool interrupted : 1;
|
||||
} qk_tap_dance_state_t;
|
||||
|
||||
# define TD(n) (QK_TAP_DANCE | ((n)&0xFF))
|
||||
|
||||
typedef void (*qk_tap_dance_user_fn_t)(qk_tap_dance_state_t *state, void *user_data);
|
||||
|
||||
typedef struct {
|
||||
qk_tap_dance_state_t state;
|
||||
struct {
|
||||
qk_tap_dance_user_fn_t on_each_tap;
|
||||
qk_tap_dance_user_fn_t on_dance_finished;
|
||||
qk_tap_dance_user_fn_t on_reset;
|
||||
} fn;
|
||||
qk_tap_dance_state_t state;
|
||||
uint16_t custom_tapping_term;
|
||||
void * user_data;
|
||||
void *user_data;
|
||||
} qk_tap_dance_action_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -62,31 +59,31 @@ typedef struct {
|
||||
# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \
|
||||
{ .fn = {qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset}, .user_data = (void *)&((qk_tap_dance_pair_t){kc1, kc2}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) \
|
||||
# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \
|
||||
{ .fn = {qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_move}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \
|
||||
{ .fn = {NULL, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_invert}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) ACTION_TAP_DANCE_DUAL_ROLE(kc, layer)
|
||||
|
||||
# define ACTION_TAP_DANCE_FN(user_fn) \
|
||||
{ .fn = {NULL, user_fn, NULL}, .user_data = NULL, }
|
||||
|
||||
# define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \
|
||||
{ .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, }
|
||||
|
||||
# define ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term) \
|
||||
{ .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, .custom_tapping_term = tap_specific_tapping_term, }
|
||||
# define TD(n) (QK_TAP_DANCE | TD_INDEX(n))
|
||||
# define TD_INDEX(code) ((code)&0xFF)
|
||||
# define TAP_DANCE_KEYCODE(state) TD(((qk_tap_dance_action_t *)state) - tap_dance_actions)
|
||||
|
||||
extern qk_tap_dance_action_t tap_dance_actions[];
|
||||
|
||||
void reset_tap_dance(qk_tap_dance_state_t *state);
|
||||
|
||||
/* To be used internally */
|
||||
|
||||
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record);
|
||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
|
||||
void tap_dance_task(void);
|
||||
void reset_tap_dance(qk_tap_dance_state_t *state);
|
||||
|
||||
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
|
||||
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
|
||||
@@ -1,330 +0,0 @@
|
||||
/* Copyright 2017 Jack Humbert
|
||||
*
|
||||
* 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 "process_terminal.h"
|
||||
#include <string.h>
|
||||
#include "version.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef CMD_BUFF_SIZE
|
||||
# define CMD_BUFF_SIZE 5
|
||||
#endif
|
||||
|
||||
bool terminal_enabled = false;
|
||||
char buffer[80] = "";
|
||||
char cmd_buffer[CMD_BUFF_SIZE][80];
|
||||
bool cmd_buffer_enabled = true; // replace with ifdef?
|
||||
char newline[2] = "\n";
|
||||
char arguments[6][20];
|
||||
bool firstTime = true;
|
||||
|
||||
short int current_cmd_buffer_pos = 0; // used for up/down arrows - keeps track of where you are in the command buffer
|
||||
|
||||
__attribute__((weak)) const char terminal_prompt[8] = "> ";
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
# ifndef TERMINAL_SONG
|
||||
# define TERMINAL_SONG SONG(TERMINAL_SOUND)
|
||||
# endif
|
||||
float terminal_song[][2] = TERMINAL_SONG;
|
||||
# define TERMINAL_BELL() PLAY_SONG(terminal_song)
|
||||
#else
|
||||
# define TERMINAL_BELL()
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) const char keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t', ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/'};
|
||||
|
||||
__attribute__((weak)) const char shifted_keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t', ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?'};
|
||||
|
||||
struct stringcase {
|
||||
char *string;
|
||||
void (*func)(void);
|
||||
} typedef stringcase;
|
||||
|
||||
void enable_terminal(void) {
|
||||
terminal_enabled = true;
|
||||
strcpy(buffer, "");
|
||||
memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
|
||||
for (int i = 0; i < 6; i++)
|
||||
strcpy(arguments[i], "");
|
||||
// select all text to start over
|
||||
// SEND_STRING(SS_LCTL("a"));
|
||||
send_string(terminal_prompt);
|
||||
}
|
||||
|
||||
void disable_terminal(void) {
|
||||
terminal_enabled = false;
|
||||
SEND_STRING("\n");
|
||||
}
|
||||
|
||||
void push_to_cmd_buffer(void) {
|
||||
if (cmd_buffer_enabled) {
|
||||
if (cmd_buffer == NULL) {
|
||||
return;
|
||||
} else {
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
strcpy(cmd_buffer[0], buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = CMD_BUFF_SIZE - 1; i > 0; --i) {
|
||||
strncpy(cmd_buffer[i], cmd_buffer[i - 1], 80);
|
||||
}
|
||||
|
||||
strcpy(cmd_buffer[0], buffer);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_about(void) {
|
||||
SEND_STRING("QMK Firmware\n");
|
||||
SEND_STRING(" v");
|
||||
SEND_STRING(QMK_VERSION);
|
||||
SEND_STRING("\n" SS_TAP(X_HOME) " Built: ");
|
||||
SEND_STRING(QMK_BUILDDATE);
|
||||
send_string(newline);
|
||||
#ifdef TERMINAL_HELP
|
||||
if (strlen(arguments[1]) != 0) {
|
||||
SEND_STRING("You entered: ");
|
||||
send_string(arguments[1]);
|
||||
send_string(newline);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void terminal_help(void);
|
||||
|
||||
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
|
||||
void terminal_keycode(void) {
|
||||
if (strlen(arguments[1]) != 0 && strlen(arguments[2]) != 0 && strlen(arguments[3]) != 0) {
|
||||
char keycode_dec[5];
|
||||
char keycode_hex[5];
|
||||
uint16_t layer = strtol(arguments[1], (char **)NULL, 10);
|
||||
uint16_t row = strtol(arguments[2], (char **)NULL, 10);
|
||||
uint16_t col = strtol(arguments[3], (char **)NULL, 10);
|
||||
uint16_t keycode = pgm_read_word(&keymaps[layer][row][col]);
|
||||
itoa(keycode, keycode_dec, 10);
|
||||
itoa(keycode, keycode_hex, 16);
|
||||
SEND_STRING("0x");
|
||||
send_string(keycode_hex);
|
||||
SEND_STRING(" (");
|
||||
send_string(keycode_dec);
|
||||
SEND_STRING(")\n");
|
||||
} else {
|
||||
#ifdef TERMINAL_HELP
|
||||
SEND_STRING("usage: keycode <layer> <row> <col>\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_keymap(void) {
|
||||
if (strlen(arguments[1]) != 0) {
|
||||
uint16_t layer = strtol(arguments[1], (char **)NULL, 10);
|
||||
for (int r = 0; r < MATRIX_ROWS; r++) {
|
||||
for (int c = 0; c < MATRIX_COLS; c++) {
|
||||
uint16_t keycode = pgm_read_word(&keymaps[layer][r][c]);
|
||||
char keycode_s[8];
|
||||
sprintf(keycode_s, "0x%04x,", keycode);
|
||||
send_string(keycode_s);
|
||||
}
|
||||
send_string(newline);
|
||||
}
|
||||
} else {
|
||||
#ifdef TERMINAL_HELP
|
||||
SEND_STRING("usage: keymap <layer>\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void print_cmd_buff(void) {
|
||||
/* without the below wait, a race condition can occur wherein the
|
||||
buffer can be printed before it has been fully moved */
|
||||
wait_ms(250);
|
||||
for (int i = 0; i < CMD_BUFF_SIZE; i++) {
|
||||
char tmpChar = ' ';
|
||||
itoa(i, &tmpChar, 10);
|
||||
const char *tmpCnstCharStr = &tmpChar; // because sned_string wont take a normal char *
|
||||
send_string(tmpCnstCharStr);
|
||||
SEND_STRING(". ");
|
||||
send_string(cmd_buffer[i]);
|
||||
SEND_STRING("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void flush_cmd_buffer(void) {
|
||||
memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
|
||||
SEND_STRING("Buffer Cleared!\n");
|
||||
}
|
||||
|
||||
stringcase terminal_cases[] = {{"about", terminal_about}, {"help", terminal_help}, {"keycode", terminal_keycode}, {"keymap", terminal_keymap}, {"flush-buffer", flush_cmd_buffer}, {"print-buffer", print_cmd_buff}, {"exit", disable_terminal}};
|
||||
|
||||
void terminal_help(void) {
|
||||
SEND_STRING("commands available:\n ");
|
||||
for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
|
||||
send_string(case_p->string);
|
||||
SEND_STRING(" ");
|
||||
}
|
||||
send_string(newline);
|
||||
}
|
||||
|
||||
void command_not_found(void) {
|
||||
wait_ms(50); // sometimes buffer isnt grabbed quick enough
|
||||
SEND_STRING("command \"");
|
||||
send_string(buffer);
|
||||
SEND_STRING("\" not found\n");
|
||||
}
|
||||
|
||||
void process_terminal_command(void) {
|
||||
// we capture return bc of the order of events, so we need to manually send a newline
|
||||
send_string(newline);
|
||||
|
||||
char * pch;
|
||||
uint8_t i = 0;
|
||||
pch = strtok(buffer, " ");
|
||||
while (pch != NULL) {
|
||||
strcpy(arguments[i], pch);
|
||||
pch = strtok(NULL, " ");
|
||||
i++;
|
||||
}
|
||||
|
||||
bool command_found = false;
|
||||
for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
|
||||
if (0 == strcmp(case_p->string, buffer)) {
|
||||
command_found = true;
|
||||
(*case_p->func)();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!command_found) command_not_found();
|
||||
|
||||
if (terminal_enabled) {
|
||||
strcpy(buffer, "");
|
||||
for (int i = 0; i < 6; i++)
|
||||
strcpy(arguments[i], "");
|
||||
SEND_STRING(SS_TAP(X_HOME));
|
||||
send_string(terminal_prompt);
|
||||
}
|
||||
}
|
||||
void check_pos(void) {
|
||||
if (current_cmd_buffer_pos >= CMD_BUFF_SIZE) { // if over the top, move it back down to the top of the buffer so you can climb back down...
|
||||
current_cmd_buffer_pos = CMD_BUFF_SIZE - 1;
|
||||
} else if (current_cmd_buffer_pos < 0) { //...and if you fall under the bottom of the buffer, reset back to 0 so you can climb back up
|
||||
current_cmd_buffer_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_terminal(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == TERM_ON && record->event.pressed) {
|
||||
enable_terminal();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (terminal_enabled && record->event.pressed) {
|
||||
if (keycode == TERM_OFF && record->event.pressed) {
|
||||
disable_terminal();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
|
||||
keycode = keycode & 0xFF;
|
||||
}
|
||||
|
||||
if (keycode < 256) {
|
||||
uint8_t str_len;
|
||||
char char_to_add;
|
||||
switch (keycode) {
|
||||
case KC_ENTER:
|
||||
case KC_KP_ENTER:
|
||||
push_to_cmd_buffer();
|
||||
current_cmd_buffer_pos = 0;
|
||||
process_terminal_command();
|
||||
return false;
|
||||
break;
|
||||
case KC_ESCAPE:
|
||||
SEND_STRING("\n");
|
||||
enable_terminal();
|
||||
return false;
|
||||
break;
|
||||
case KC_BACKSPACE:
|
||||
str_len = strlen(buffer);
|
||||
if (str_len > 0) {
|
||||
buffer[str_len - 1] = 0;
|
||||
return true;
|
||||
} else {
|
||||
TERMINAL_BELL();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case KC_LEFT:
|
||||
return false;
|
||||
break;
|
||||
case KC_RIGHT:
|
||||
return false;
|
||||
break;
|
||||
case KC_UP: // 0 = recent
|
||||
check_pos(); // check our current buffer position is valid
|
||||
if (current_cmd_buffer_pos <= CMD_BUFF_SIZE - 1) { // once we get to the top, dont do anything
|
||||
str_len = strlen(buffer);
|
||||
for (int i = 0; i < str_len; ++i) {
|
||||
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
|
||||
// process_terminal(KC_BACKSPACE,record);
|
||||
}
|
||||
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80);
|
||||
|
||||
send_string(buffer);
|
||||
++current_cmd_buffer_pos; // get ready to access the above cmd if up/down is pressed again
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_DOWN:
|
||||
check_pos();
|
||||
if (current_cmd_buffer_pos >= 0) { // once we get to the bottom, dont do anything
|
||||
str_len = strlen(buffer);
|
||||
for (int i = 0; i < str_len; ++i) {
|
||||
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
|
||||
// process_terminal(KC_BACKSPACE,record);
|
||||
}
|
||||
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79);
|
||||
|
||||
send_string(buffer);
|
||||
--current_cmd_buffer_pos; // get ready to access the above cmd if down/up is pressed again
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (keycode <= 58) {
|
||||
char_to_add = 0;
|
||||
if (get_mods() & (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))) {
|
||||
char_to_add = shifted_keycode_to_ascii_lut[keycode];
|
||||
} else if (get_mods() == 0) {
|
||||
char_to_add = keycode_to_ascii_lut[keycode];
|
||||
}
|
||||
if (char_to_add != 0) {
|
||||
strncat(buffer, &char_to_add, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/* Copyright 2017 Jack Humbert
|
||||
*
|
||||
* 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 "quantum.h"
|
||||
|
||||
extern const char keycode_to_ascii_lut[58];
|
||||
extern const char shifted_keycode_to_ascii_lut[58];
|
||||
extern const char terminal_prompt[8];
|
||||
bool process_terminal(uint16_t keycode, keyrecord_t *record);
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Copyright 2017 Jack Humbert
|
||||
*
|
||||
* 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 "quantum.h"
|
||||
|
||||
#define TERM_ON KC_NO
|
||||
#define TERM_OFF KC_NO
|
||||
@@ -117,6 +117,12 @@ __attribute__((weak)) void unicode_input_start(void) {
|
||||
tap_code(UNICODE_KEY_WINC);
|
||||
tap_code(KC_U);
|
||||
break;
|
||||
case UC_EMACS:
|
||||
// The usual way to type unicode in emacs is C-x-8 <RET> then the unicode number in hex
|
||||
tap_code16(LCTL(KC_X));
|
||||
tap_code16(KC_8);
|
||||
tap_code16(KC_ENTER);
|
||||
break;
|
||||
}
|
||||
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
@@ -142,6 +148,9 @@ __attribute__((weak)) void unicode_input_finish(void) {
|
||||
case UC_WINC:
|
||||
tap_code(KC_ENTER);
|
||||
break;
|
||||
case UC_EMACS:
|
||||
tap_code16(KC_ENTER);
|
||||
break;
|
||||
}
|
||||
|
||||
set_mods(unicode_saved_mods); // Reregister previously set mods
|
||||
@@ -167,6 +176,9 @@ __attribute__((weak)) void unicode_input_cancel(void) {
|
||||
tap_code(KC_NUM_LOCK);
|
||||
}
|
||||
break;
|
||||
case UC_EMACS:
|
||||
tap_code16(LCTL(KC_G)); // C-g cancels
|
||||
break;
|
||||
}
|
||||
|
||||
set_mods(unicode_saved_mods); // Reregister previously set mods
|
||||
@@ -299,14 +311,30 @@ bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
|
||||
cycle_unicode_input_mode(shifted ? +1 : -1);
|
||||
audio_helper();
|
||||
break;
|
||||
|
||||
case UNICODE_MODE_MAC ... UNICODE_MODE_WINC: {
|
||||
// Keycodes and input modes follow the same ordering
|
||||
uint8_t delta = keycode - UNICODE_MODE_MAC;
|
||||
set_unicode_input_mode(UC_MAC + delta);
|
||||
case UNICODE_MODE_MAC:
|
||||
set_unicode_input_mode(UC_MAC);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_LNX:
|
||||
set_unicode_input_mode(UC_LNX);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_WIN:
|
||||
set_unicode_input_mode(UC_WIN);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_BSD:
|
||||
set_unicode_input_mode(UC_BSD);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_WINC:
|
||||
set_unicode_input_mode(UC_WINC);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_EMACS:
|
||||
set_unicode_input_mode(UC_EMACS);
|
||||
audio_helper();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ enum unicode_input_modes {
|
||||
UC_WIN, // Windows using EnableHexNumpad
|
||||
UC_BSD, // BSD (not implemented)
|
||||
UC_WINC, // Windows using WinCompose (https://github.com/samhocevar/wincompose)
|
||||
UC_EMACS, // Emacs is an operating system in search of a good text editor
|
||||
UC__COUNT // Number of available input modes (always leave at the end)
|
||||
};
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ int qmk_settings_set(uint16_t qsid, const void *setting, size_t maxsz) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
uint16_t qs_get_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
return QS.tapping_term;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include "quantum/action.h"
|
||||
|
||||
/* take qmk config macros and set up helper variables for default settings */
|
||||
|
||||
@@ -147,6 +148,8 @@ void qmk_settings_query(uint16_t qsid_gt, void *buffer, size_t sz);
|
||||
int qmk_settings_get(uint16_t qsid, void *setting, size_t maxsz);
|
||||
int qmk_settings_set(uint16_t qsid, const void *setting, size_t maxsz);
|
||||
|
||||
uint16_t qs_get_tapping_term(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
extern qmk_settings_t QS;
|
||||
|
||||
/* Grave escape */
|
||||
|
||||
@@ -99,16 +99,27 @@ __attribute__((weak)) void unregister_code16(uint16_t code) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void tap_code16(uint16_t code) {
|
||||
/** \brief Tap a keycode with a delay.
|
||||
*
|
||||
* \param code The modded keycode to tap.
|
||||
* \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it.
|
||||
*/
|
||||
__attribute__((weak)) void tap_code16_delay(uint16_t code, uint16_t delay) {
|
||||
register_code16(code);
|
||||
if (code == KC_CAPS_LOCK) {
|
||||
qs_wait_ms(QS_tap_hold_caps_delay);
|
||||
} else if (TAP_CODE_DELAY > 0) {
|
||||
qs_wait_ms(QS_tap_code_delay);
|
||||
for (uint16_t i = delay; i > 0; i--) {
|
||||
wait_ms(1);
|
||||
}
|
||||
unregister_code16(code);
|
||||
}
|
||||
|
||||
/** \brief Tap a keycode with the default delay.
|
||||
*
|
||||
* \param code The modded keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
|
||||
*/
|
||||
__attribute__((weak)) void tap_code16(uint16_t code) {
|
||||
tap_code16_delay(code, code == KC_CAPS_LOCK ? QS_tap_hold_caps_delay : QS_tap_code_delay);
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool process_action_kb(keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
@@ -318,9 +329,6 @@ bool process_record_quantum_helper(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifdef DYNAMIC_TAPPING_TERM_ENABLE
|
||||
process_dynamic_tapping_term(keycode, record) &&
|
||||
#endif
|
||||
#ifdef TERMINAL_ENABLE
|
||||
process_terminal(keycode, record) &&
|
||||
#endif
|
||||
#ifdef SPACE_CADET_ENABLE
|
||||
process_space_cadet(keycode, record) &&
|
||||
#endif
|
||||
@@ -414,6 +422,9 @@ bool process_record_quantum_helper(uint16_t keycode, keyrecord_t *record) {
|
||||
SEND_STRING_DELAY(" compile ", TAP_CODE_DELAY);
|
||||
}
|
||||
SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP SS_TAP(X_ENTER), TAP_CODE_DELAY);
|
||||
if (temp_mod & MOD_MASK_SHIFT && temp_mod & MOD_MASK_CTRL) {
|
||||
reset_keyboard();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include "action_util.h"
|
||||
#include "action_tapping.h"
|
||||
#include "print.h"
|
||||
#include "send_string.h"
|
||||
#include "suspend.h"
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -141,12 +140,6 @@ extern layer_state_t layer_state;
|
||||
# include "process_key_lock.h"
|
||||
#endif
|
||||
|
||||
#ifdef TERMINAL_ENABLE
|
||||
# include "process_terminal.h"
|
||||
#else
|
||||
# include "process_terminal_nop.h"
|
||||
#endif
|
||||
|
||||
#ifdef SPACE_CADET_ENABLE
|
||||
# include "process_space_cadet.h"
|
||||
#endif
|
||||
@@ -175,6 +168,10 @@ extern layer_state_t layer_state;
|
||||
# include "hd44780.h"
|
||||
#endif
|
||||
|
||||
#ifdef SEND_STRING_ENABLE
|
||||
# include "send_string.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAPTIC_ENABLE
|
||||
# include "haptic.h"
|
||||
# include "process_haptic.h"
|
||||
@@ -268,6 +265,7 @@ void shutdown_user(void);
|
||||
void register_code16(uint16_t code);
|
||||
void unregister_code16(uint16_t code);
|
||||
void tap_code16(uint16_t code);
|
||||
void tap_code16_delay(uint16_t code, uint16_t delay);
|
||||
|
||||
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);
|
||||
|
||||
@@ -473,9 +473,9 @@ enum quantum_keycodes {
|
||||
// Lock Key
|
||||
KC_LOCK, // 5D2B
|
||||
|
||||
// Terminal
|
||||
TERM_ON, // 5D2C
|
||||
TERM_OFF, // 5D2D
|
||||
// Unused slots
|
||||
UNUSED_000, // 5D2C
|
||||
UNUSED_001, // 5D2D
|
||||
|
||||
// Sequencer
|
||||
SQ_ON, // 5D2E
|
||||
@@ -605,6 +605,12 @@ enum quantum_keycodes {
|
||||
|
||||
CAPS_WORD,
|
||||
|
||||
MAGIC_SWAP_ESCAPE_CAPSLOCK,
|
||||
MAGIC_UNSWAP_ESCAPE_CAPSLOCK,
|
||||
MAGIC_TOGGLE_ESCAPE_CAPSLOCK,
|
||||
|
||||
UNICODE_MODE_EMACS,
|
||||
|
||||
// Start of custom keycode range for keyboards and keymaps - always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
@@ -756,6 +762,10 @@ enum quantum_keycodes {
|
||||
#define CL_CAPS MAGIC_UNCAPSLOCK_TO_CONTROL
|
||||
#define CL_TOGG MAGIC_TOGGLE_CONTROL_CAPSLOCK
|
||||
|
||||
#define EC_SWAP MAGIC_SWAP_ESCAPE_CAPSLOCK
|
||||
#define EC_NORM MAGIC_UNSWAP_ESCAPE_CAPSLOCK
|
||||
#define EC_TOGG MAGIC_TOGGLE_ESCAPE_CAPSLOCK
|
||||
|
||||
#define LCG_SWP MAGIC_SWAP_LCTL_LGUI
|
||||
#define LCG_NRM MAGIC_UNSWAP_LCTL_LGUI
|
||||
#define RCG_SWP MAGIC_SWAP_RCTL_RGUI
|
||||
@@ -789,15 +799,8 @@ enum quantum_keycodes {
|
||||
#define EH_LEFT MAGIC_EE_HANDS_LEFT
|
||||
#define EH_RGHT MAGIC_EE_HANDS_RIGHT
|
||||
|
||||
// GOTO layer - 16 layers max
|
||||
// when:
|
||||
// ON_PRESS = 1
|
||||
// ON_RELEASE = 2
|
||||
// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
|
||||
// In fact, we changed it to assume ON_PRESS for sanity/simplicity. If needed, you can add your own
|
||||
// keycode modeled after the old version, kept below for this.
|
||||
/* #define TO(layer, when) (QK_TO | (when << 0x4) | (layer & 0xFF)) */
|
||||
#define TO(layer) (QK_TO | (ON_PRESS << 0x4) | ((layer)&0xFF))
|
||||
// GOTO layer - 256 layer max
|
||||
#define TO(layer) (QK_TO | ((layer)&0xFF))
|
||||
|
||||
// Momentary switch layer - 256 layer max
|
||||
#define MO(layer) (QK_MOMENTARY | ((layer)&0xFF))
|
||||
@@ -893,6 +896,7 @@ enum quantum_keycodes {
|
||||
#define UC_M_WI UNICODE_MODE_WIN
|
||||
#define UC_M_BS UNICODE_MODE_BSD
|
||||
#define UC_M_WC UNICODE_MODE_WINC
|
||||
#define UC_M_EM UNICODE_MODE_EMACS
|
||||
|
||||
// Swap Hands
|
||||
#define SH_T(kc) (QK_SWAP_HANDS | (kc))
|
||||
|
||||
@@ -11,3 +11,6 @@
|
||||
|
||||
#define KC_GESC QK_GRAVE_ESCAPE
|
||||
#define EEP_RST QK_CLEAR_EEPROM
|
||||
|
||||
#define TERM_ON _Static_assert(false, "The Terminal feature has been removed from QMK. Please remove use of TERM_ON/TERM_OFF from your keymap.")
|
||||
#define TERM_OFF _Static_assert(false, "The Terminal feature has been removed from QMK.. Please remove use of TERM_ON/TERM_OFF from your keymap.")
|
||||
@@ -1,19 +1,5 @@
|
||||
/* Copyright (C) 2021 @filterpaper
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2022 @filterpaper
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Inspired from 4x12 fractal created by @schwarzgrau
|
||||
|
||||
#ifdef ENABLE_RGB_MATRIX_PIXEL_FRACTAL
|
||||
@@ -23,12 +9,8 @@ RGB_MATRIX_EFFECT(PIXEL_FRACTAL)
|
||||
|
||||
static bool PIXEL_FRACTAL(effect_params_t* params) {
|
||||
# define MID_COL MATRIX_COLS / 2
|
||||
static bool led[MATRIX_ROWS][MATRIX_COLS];
|
||||
|
||||
static bool led[MATRIX_ROWS][MID_COL];
|
||||
static uint32_t wait_timer = 0;
|
||||
if (wait_timer > g_rgb_timer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint32_t interval(void) {
|
||||
return 3000 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16);
|
||||
@@ -38,44 +20,40 @@ static bool PIXEL_FRACTAL(effect_params_t* params) {
|
||||
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
|
||||
if (led[h][l]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][l], rgb.r, rgb.g, rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][l], 0, 0, 0);
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
|
||||
if (g_rgb_timer > wait_timer) {
|
||||
RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv);
|
||||
for (uint8_t h = 0; h < MATRIX_ROWS; ++h) {
|
||||
// Light and copy columns outward
|
||||
for (uint8_t l = 0; l < MID_COL - 1; ++l) {
|
||||
if (led[h][l]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][l], rgb.r, rgb.g, rgb.b);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MATRIX_COLS - 1 - l], rgb.r, rgb.g, rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][l], 0, 0, 0);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MATRIX_COLS - 1 - l], 0, 0, 0);
|
||||
}
|
||||
led[h][l] = led[h][l + 1];
|
||||
}
|
||||
led[h][l] = led[h][l + 1];
|
||||
}
|
||||
|
||||
for (uint8_t r = MATRIX_COLS - 1; r > MID_COL; --r) { // Light and move right columns outwards
|
||||
if (led[h][r]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][r], rgb.r, rgb.g, rgb.b);
|
||||
// Light both middle columns
|
||||
if (led[h][MID_COL - 1]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], rgb.r, rgb.g, rgb.b);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MATRIX_COLS - MID_COL], rgb.r, rgb.g, rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][r], 0, 0, 0);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], 0, 0, 0);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MATRIX_COLS - MID_COL], 0, 0, 0);
|
||||
}
|
||||
led[h][r] = led[h][r - 1];
|
||||
|
||||
// Generate new random fractal column
|
||||
led[h][MID_COL - 1] = (random8() & 3) ? false : true;
|
||||
}
|
||||
|
||||
// Light both middle columns
|
||||
if (led[h][MID_COL]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], rgb.r, rgb.g, rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], 0, 0, 0);
|
||||
}
|
||||
if (led[h][MID_COL - 1]) {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], rgb.r, rgb.g, rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], 0, 0, 0);
|
||||
}
|
||||
|
||||
// Generate new random fractal columns
|
||||
led[h][MID_COL] = led[h][MID_COL - 1] = (random8() & 3) ? false : true;
|
||||
wait_timer = g_rgb_timer + interval();
|
||||
}
|
||||
|
||||
wait_timer = g_rgb_timer + interval();
|
||||
return false;
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_RGB_MATRIX_PIXEL_FRACTAL
|
||||
|
||||
@@ -21,17 +21,14 @@ RGB_MATRIX_EFFECT(PIXEL_RAIN)
|
||||
|
||||
static bool PIXEL_RAIN(effect_params_t* params) {
|
||||
static uint32_t wait_timer = 0;
|
||||
if (wait_timer > g_rgb_timer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint32_t interval(void) {
|
||||
return 500 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16);
|
||||
}
|
||||
|
||||
bool rain_pixel(uint8_t i, effect_params_t * params, bool off) {
|
||||
void rain_pixel(uint8_t i, effect_params_t * params, bool off) {
|
||||
if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (off) {
|
||||
rgb_matrix_set_color(i, 0, 0, 0);
|
||||
@@ -41,10 +38,13 @@ static bool PIXEL_RAIN(effect_params_t* params) {
|
||||
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
wait_timer = g_rgb_timer + interval();
|
||||
return false;
|
||||
}
|
||||
|
||||
return rain_pixel(mod8(random8(), DRIVER_LED_TOTAL), params, random8() & 2);
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
if (g_rgb_timer > wait_timer) {
|
||||
rain_pixel(mod8(random8(), DRIVER_LED_TOTAL), params, random8() & 2);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
@@ -15,23 +15,22 @@ static void raindrops_set_color(int i, effect_params_t* params) {
|
||||
deltaH += 256;
|
||||
}
|
||||
|
||||
hsv.h = rgb_matrix_config.hsv.h + (deltaH * (rand() & 0x03));
|
||||
hsv.h = rgb_matrix_config.hsv.h + (deltaH * (random8() & 0x03));
|
||||
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
|
||||
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
|
||||
bool RAINDROPS(effect_params_t* params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
if (!params->init) {
|
||||
// Change one LED every tick, make sure speed is not 0
|
||||
if (scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 16)) % 10 == 0) {
|
||||
raindrops_set_color(rand() % DRIVER_LED_TOTAL, params);
|
||||
raindrops_set_color(random8() % DRIVER_LED_TOTAL, params);
|
||||
}
|
||||
} else {
|
||||
for (int i = led_min; i < led_max; i++) {
|
||||
raindrops_set_color(i, params);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
for (int i = led_min; i < led_max; i++) {
|
||||
raindrops_set_color(i, params);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ RGB_MATRIX_EFFECT(SOLID_REACTIVE)
|
||||
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static HSV SOLID_REACTIVE_math(HSV hsv, uint16_t offset) {
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, add8(rgb_matrix_config.speed, 1) >> 6);
|
||||
# endif
|
||||
hsv.h += qsub8(130, offset);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ static HSV SOLID_REACTIVE_CROSS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
|
||||
dy = dy * 16 > 255 ? 255 : dy * 16;
|
||||
effect += dx > dy ? dy : dx;
|
||||
if (effect > 255) effect = 255;
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, add8(rgb_matrix_config.speed, 1) >> 6);
|
||||
# endif
|
||||
hsv.v = qadd8(hsv.v, 255 - effect);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ static HSV SOLID_REACTIVE_NEXUS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
|
||||
if (effect > 255) effect = 255;
|
||||
if (dist > 72) effect = 255;
|
||||
if ((dx > 8 || dx < -8) && (dy > 8 || dy < -8)) effect = 255;
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, add8(rgb_matrix_config.speed, 1) >> 6);
|
||||
# endif
|
||||
hsv.v = qadd8(hsv.v, 255 - effect);
|
||||
hsv.h = rgb_matrix_config.hsv.h + dy / 4;
|
||||
return hsv;
|
||||
|
||||
@@ -5,6 +5,9 @@ RGB_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
|
||||
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static HSV SOLID_REACTIVE_SIMPLE_math(HSV hsv, uint16_t offset) {
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, add8(rgb_matrix_config.speed, 1) >> 6);
|
||||
# endif
|
||||
hsv.v = scale8(255 - offset, hsv.v);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE)
|
||||
static HSV SOLID_REACTIVE_WIDE_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
|
||||
uint16_t effect = tick + dist * 5;
|
||||
if (effect > 255) effect = 255;
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, add8(rgb_matrix_config.speed, 1) >> 6);
|
||||
# endif
|
||||
hsv.v = qadd8(hsv.v, 255 - effect);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
@@ -7,30 +7,41 @@ RGB_MATRIX_EFFECT(TYPING_HEATMAP)
|
||||
# define RGB_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 25
|
||||
# endif
|
||||
|
||||
# ifndef RGB_MATRIX_TYPING_HEATMAP_SPREAD
|
||||
# define RGB_MATRIX_TYPING_HEATMAP_SPREAD 40
|
||||
# endif
|
||||
|
||||
# ifndef RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT
|
||||
# define RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
|
||||
# endif
|
||||
void process_rgb_matrix_typing_heatmap(uint8_t row, uint8_t col) {
|
||||
# ifdef RGB_MATRIX_TYPING_HEATMAP_SLIM
|
||||
// Limit effect to pressed keys
|
||||
g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
|
||||
# else
|
||||
uint8_t m_row = row - 1;
|
||||
uint8_t p_row = row + 1;
|
||||
uint8_t m_col = col - 1;
|
||||
uint8_t p_col = col + 1;
|
||||
|
||||
if (m_col < col) g_rgb_frame_buffer[row][m_col] = qadd8(g_rgb_frame_buffer[row][m_col], 16);
|
||||
g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
|
||||
if (p_col < MATRIX_COLS) g_rgb_frame_buffer[row][p_col] = qadd8(g_rgb_frame_buffer[row][p_col], 16);
|
||||
|
||||
if (p_row < MATRIX_ROWS) {
|
||||
if (m_col < col) g_rgb_frame_buffer[p_row][m_col] = qadd8(g_rgb_frame_buffer[p_row][m_col], 13);
|
||||
g_rgb_frame_buffer[p_row][col] = qadd8(g_rgb_frame_buffer[p_row][col], 16);
|
||||
if (p_col < MATRIX_COLS) g_rgb_frame_buffer[p_row][p_col] = qadd8(g_rgb_frame_buffer[p_row][p_col], 13);
|
||||
if (g_led_config.matrix_co[row][col] == NO_LED) { // skip as pressed key doesn't have an led position
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_row < row) {
|
||||
if (m_col < col) g_rgb_frame_buffer[m_row][m_col] = qadd8(g_rgb_frame_buffer[m_row][m_col], 13);
|
||||
g_rgb_frame_buffer[m_row][col] = qadd8(g_rgb_frame_buffer[m_row][col], 16);
|
||||
if (p_col < MATRIX_COLS) g_rgb_frame_buffer[m_row][p_col] = qadd8(g_rgb_frame_buffer[m_row][p_col], 13);
|
||||
for (uint8_t i_row = 0; i_row < MATRIX_ROWS; i_row++) {
|
||||
for (uint8_t i_col = 0; i_col < MATRIX_COLS; i_col++) {
|
||||
if (g_led_config.matrix_co[i_row][i_col] == NO_LED) { // skip as target key doesn't have an led position
|
||||
continue;
|
||||
}
|
||||
if (i_row == row && i_col == col) {
|
||||
g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
|
||||
} else {
|
||||
# define LED_DISTANCE(led_a, led_b) sqrt16(((int8_t)(led_a.x - led_b.x) * (int8_t)(led_a.x - led_b.x)) + ((int8_t)(led_a.y - led_b.y) * (int8_t)(led_a.y - led_b.y)))
|
||||
uint8_t distance = LED_DISTANCE(g_led_config.point[g_led_config.matrix_co[row][col]], g_led_config.point[g_led_config.matrix_co[i_row][i_col]]);
|
||||
# undef LED_DISTANCE
|
||||
if (distance <= RGB_MATRIX_TYPING_HEATMAP_SPREAD) {
|
||||
uint8_t amount = qsub8(RGB_MATRIX_TYPING_HEATMAP_SPREAD, distance);
|
||||
if (amount > RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT) {
|
||||
amount = RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT;
|
||||
}
|
||||
g_rgb_frame_buffer[i_row][i_col] = qadd8(g_rgb_frame_buffer[i_row][i_col], amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
@@ -41,10 +52,7 @@ static uint16_t heatmap_decrease_timer;
|
||||
static bool decrease_heatmap_values;
|
||||
|
||||
bool TYPING_HEATMAP(effect_params_t* params) {
|
||||
// Modified version of RGB_MATRIX_USE_LIMITS to work off of matrix row / col size
|
||||
uint8_t led_min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter;
|
||||
uint8_t led_max = led_min + RGB_MATRIX_LED_PROCESS_LIMIT;
|
||||
if (led_max > sizeof(g_rgb_frame_buffer)) led_max = sizeof(g_rgb_frame_buffer);
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
|
||||
if (params->init) {
|
||||
rgb_matrix_set_color_all(0, 0, 0);
|
||||
@@ -64,28 +72,26 @@ bool TYPING_HEATMAP(effect_params_t* params) {
|
||||
}
|
||||
|
||||
// Render heatmap & decrease
|
||||
for (int i = led_min; i < led_max; i++) {
|
||||
uint8_t row = i % MATRIX_ROWS;
|
||||
uint8_t col = i / MATRIX_ROWS;
|
||||
uint8_t val = g_rgb_frame_buffer[row][col];
|
||||
uint8_t count = 0;
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS && count < RGB_MATRIX_LED_PROCESS_LIMIT; row++) {
|
||||
for (uint8_t col = 0; col < MATRIX_COLS && RGB_MATRIX_LED_PROCESS_LIMIT; col++) {
|
||||
if (g_led_config.matrix_co[row][col] >= led_min && g_led_config.matrix_co[row][col] < led_max) {
|
||||
count++;
|
||||
uint8_t val = g_rgb_frame_buffer[row][col];
|
||||
if (!HAS_ANY_FLAGS(g_led_config.flags[g_led_config.matrix_co[row][col]], params->flags)) continue;
|
||||
|
||||
// set the pixel colour
|
||||
uint8_t led[LED_HITS_TO_REMEMBER];
|
||||
uint8_t led_count = rgb_matrix_map_row_column_to_led(row, col, led);
|
||||
for (uint8_t j = 0; j < led_count; ++j) {
|
||||
if (!HAS_ANY_FLAGS(g_led_config.flags[led[j]], params->flags)) continue;
|
||||
HSV hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
|
||||
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
|
||||
rgb_matrix_set_color(g_led_config.matrix_co[row][col], rgb.r, rgb.g, rgb.b);
|
||||
|
||||
HSV hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
|
||||
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
|
||||
rgb_matrix_set_color(led[j], rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
|
||||
if (decrease_heatmap_values) {
|
||||
g_rgb_frame_buffer[row][col] = qsub8(val, 1);
|
||||
if (decrease_heatmap_values) {
|
||||
g_rgb_frame_buffer[row][col] = qsub8(val, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return led_max < sizeof(g_rgb_frame_buffer);
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
@@ -249,8 +249,15 @@ void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) {
|
||||
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
|
||||
if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) {
|
||||
process_rgb_matrix_typing_heatmap(row, col);
|
||||
# if defined(RGB_MATRIX_KEYRELEASES)
|
||||
if (!pressed)
|
||||
# else
|
||||
if (pressed)
|
||||
# endif // defined(RGB_MATRIX_KEYRELEASES)
|
||||
{
|
||||
if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) {
|
||||
process_rgb_matrix_typing_heatmap(row, col);
|
||||
}
|
||||
}
|
||||
#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
|
||||
}
|
||||
@@ -724,10 +731,20 @@ void rgb_matrix_decrease_speed(void) {
|
||||
rgb_matrix_decrease_speed_helper(true);
|
||||
}
|
||||
|
||||
void rgb_matrix_set_flags_eeprom_helper(led_flags_t flags, bool write_to_eeprom) {
|
||||
rgb_matrix_config.flags = flags;
|
||||
eeconfig_flag_rgb_matrix(write_to_eeprom);
|
||||
dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.flags);
|
||||
}
|
||||
|
||||
led_flags_t rgb_matrix_get_flags(void) {
|
||||
return rgb_matrix_config.flags;
|
||||
}
|
||||
|
||||
void rgb_matrix_set_flags(led_flags_t flags) {
|
||||
rgb_matrix_config.flags = flags;
|
||||
rgb_matrix_set_flags_eeprom_helper(flags, true);
|
||||
}
|
||||
|
||||
void rgb_matrix_set_flags_noeeprom(led_flags_t flags) {
|
||||
rgb_matrix_set_flags_eeprom_helper(flags, false);
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ void rgb_matrix_increase_speed_noeeprom(void);
|
||||
void rgb_matrix_decrease_speed(void);
|
||||
void rgb_matrix_decrease_speed_noeeprom(void);
|
||||
led_flags_t rgb_matrix_get_flags(void);
|
||||
led_flags_t rgb_matrix_get_flags_noeeprom(void);
|
||||
void rgb_matrix_set_flags(led_flags_t flags);
|
||||
|
||||
#ifndef RGBLIGHT_ENABLE
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/* Copyright 2021
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "progmem.h"
|
||||
#include "send_string_keycodes.h"
|
||||
|
||||
#define SEND_STRING(string) send_string_P(PSTR(string))
|
||||
#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval)
|
||||
|
||||
// Look-Up Tables (LUTs) to convert ASCII character to keycode sequence.
|
||||
extern const uint8_t ascii_to_shift_lut[16];
|
||||
extern const uint8_t ascii_to_altgr_lut[16];
|
||||
extern const uint8_t ascii_to_dead_lut[16];
|
||||
extern const uint8_t ascii_to_keycode_lut[128];
|
||||
|
||||
// clang-format off
|
||||
#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \
|
||||
( ((a) ? 1 : 0) << 0 \
|
||||
| ((b) ? 1 : 0) << 1 \
|
||||
| ((c) ? 1 : 0) << 2 \
|
||||
| ((d) ? 1 : 0) << 3 \
|
||||
| ((e) ? 1 : 0) << 4 \
|
||||
| ((f) ? 1 : 0) << 5 \
|
||||
| ((g) ? 1 : 0) << 6 \
|
||||
| ((h) ? 1 : 0) << 7 )
|
||||
// clang-format on
|
||||
|
||||
void send_string(const char *str);
|
||||
void send_string_with_delay(const char *str, uint8_t interval);
|
||||
void send_string_P(const char *str);
|
||||
void send_string_with_delay_P(const char *str, uint8_t interval);
|
||||
void send_char(char ascii_code);
|
||||
|
||||
void send_dword(uint32_t number);
|
||||
void send_word(uint16_t number);
|
||||
void send_byte(uint8_t number);
|
||||
void send_nibble(uint8_t number);
|
||||
|
||||
void tap_random_base64(void);
|
||||
@@ -142,40 +142,36 @@ __attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
|
||||
// Note: we bit-pack in "reverse" order to optimize loading
|
||||
#define PGM_LOADBIT(mem, pos) ((pgm_read_byte(&((mem)[(pos) / 8])) >> ((pos) % 8)) & 0x01)
|
||||
|
||||
void send_string(const char *str) {
|
||||
send_string_with_delay(str, 0);
|
||||
void send_string(const char *string) {
|
||||
send_string_with_delay(string, 0);
|
||||
}
|
||||
|
||||
void send_string_P(const char *str) {
|
||||
send_string_with_delay_P(str, 0);
|
||||
}
|
||||
|
||||
void send_string_with_delay(const char *str, uint8_t interval) {
|
||||
void send_string_with_delay(const char *string, uint8_t interval) {
|
||||
while (1) {
|
||||
char ascii_code = *str;
|
||||
char ascii_code = *string;
|
||||
if (!ascii_code) break;
|
||||
if (ascii_code == SS_QMK_PREFIX) {
|
||||
ascii_code = *(++str);
|
||||
ascii_code = *(++string);
|
||||
if (ascii_code == SS_TAP_CODE) {
|
||||
// tap
|
||||
uint8_t keycode = *(++str);
|
||||
uint8_t keycode = *(++string);
|
||||
tap_code(keycode);
|
||||
} else if (ascii_code == SS_DOWN_CODE) {
|
||||
// down
|
||||
uint8_t keycode = *(++str);
|
||||
uint8_t keycode = *(++string);
|
||||
register_code(keycode);
|
||||
} else if (ascii_code == SS_UP_CODE) {
|
||||
// up
|
||||
uint8_t keycode = *(++str);
|
||||
uint8_t keycode = *(++string);
|
||||
unregister_code(keycode);
|
||||
} else if (ascii_code == SS_DELAY_CODE) {
|
||||
// delay
|
||||
int ms = 0;
|
||||
uint8_t keycode = *(++str);
|
||||
uint8_t keycode = *(++string);
|
||||
while (isdigit(keycode)) {
|
||||
ms *= 10;
|
||||
ms += keycode - '0';
|
||||
keycode = *(++str);
|
||||
keycode = *(++string);
|
||||
}
|
||||
while (ms--)
|
||||
wait_ms(1);
|
||||
@@ -183,50 +179,7 @@ void send_string_with_delay(const char *str, uint8_t interval) {
|
||||
} else {
|
||||
send_char(ascii_code);
|
||||
}
|
||||
++str;
|
||||
// interval
|
||||
{
|
||||
uint8_t ms = interval;
|
||||
while (ms--)
|
||||
wait_ms(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_string_with_delay_P(const char *str, uint8_t interval) {
|
||||
while (1) {
|
||||
char ascii_code = pgm_read_byte(str);
|
||||
if (!ascii_code) break;
|
||||
if (ascii_code == SS_QMK_PREFIX) {
|
||||
ascii_code = pgm_read_byte(++str);
|
||||
if (ascii_code == SS_TAP_CODE) {
|
||||
// tap
|
||||
uint8_t keycode = pgm_read_byte(++str);
|
||||
tap_code(keycode);
|
||||
} else if (ascii_code == SS_DOWN_CODE) {
|
||||
// down
|
||||
uint8_t keycode = pgm_read_byte(++str);
|
||||
register_code(keycode);
|
||||
} else if (ascii_code == SS_UP_CODE) {
|
||||
// up
|
||||
uint8_t keycode = pgm_read_byte(++str);
|
||||
unregister_code(keycode);
|
||||
} else if (ascii_code == SS_DELAY_CODE) {
|
||||
// delay
|
||||
int ms = 0;
|
||||
uint8_t keycode = pgm_read_byte(++str);
|
||||
while (isdigit(keycode)) {
|
||||
ms *= 10;
|
||||
ms += keycode - '0';
|
||||
keycode = pgm_read_byte(++str);
|
||||
}
|
||||
while (ms--)
|
||||
wait_ms(1);
|
||||
}
|
||||
} else {
|
||||
send_char(ascii_code);
|
||||
}
|
||||
++str;
|
||||
++string;
|
||||
// interval
|
||||
{
|
||||
uint8_t ms = interval;
|
||||
@@ -250,17 +203,17 @@ void send_char(char ascii_code) {
|
||||
bool is_dead = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code);
|
||||
|
||||
if (is_shifted) {
|
||||
register_code(KC_LSFT);
|
||||
register_code(KC_LEFT_SHIFT);
|
||||
}
|
||||
if (is_altgred) {
|
||||
register_code(KC_RALT);
|
||||
register_code(KC_RIGHT_ALT);
|
||||
}
|
||||
tap_code(keycode);
|
||||
if (is_altgred) {
|
||||
unregister_code(KC_RALT);
|
||||
unregister_code(KC_RIGHT_ALT);
|
||||
}
|
||||
if (is_shifted) {
|
||||
unregister_code(KC_LSFT);
|
||||
unregister_code(KC_LEFT_SHIFT);
|
||||
}
|
||||
if (is_dead) {
|
||||
tap_code(KC_SPACE);
|
||||
@@ -320,3 +273,52 @@ void tap_random_base64(void) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__AVR__)
|
||||
void send_string_P(const char *string) {
|
||||
send_string_with_delay_P(string, 0);
|
||||
}
|
||||
|
||||
void send_string_with_delay_P(const char *string, uint8_t interval) {
|
||||
while (1) {
|
||||
char ascii_code = pgm_read_byte(string);
|
||||
if (!ascii_code) break;
|
||||
if (ascii_code == SS_QMK_PREFIX) {
|
||||
ascii_code = pgm_read_byte(++string);
|
||||
if (ascii_code == SS_TAP_CODE) {
|
||||
// tap
|
||||
uint8_t keycode = pgm_read_byte(++string);
|
||||
tap_code(keycode);
|
||||
} else if (ascii_code == SS_DOWN_CODE) {
|
||||
// down
|
||||
uint8_t keycode = pgm_read_byte(++string);
|
||||
register_code(keycode);
|
||||
} else if (ascii_code == SS_UP_CODE) {
|
||||
// up
|
||||
uint8_t keycode = pgm_read_byte(++string);
|
||||
unregister_code(keycode);
|
||||
} else if (ascii_code == SS_DELAY_CODE) {
|
||||
// delay
|
||||
int ms = 0;
|
||||
uint8_t keycode = pgm_read_byte(++string);
|
||||
while (isdigit(keycode)) {
|
||||
ms *= 10;
|
||||
ms += keycode - '0';
|
||||
keycode = pgm_read_byte(++string);
|
||||
}
|
||||
while (ms--)
|
||||
wait_ms(1);
|
||||
}
|
||||
} else {
|
||||
send_char(ascii_code);
|
||||
}
|
||||
++string;
|
||||
// interval
|
||||
{
|
||||
uint8_t ms = interval;
|
||||
while (ms--)
|
||||
wait_ms(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
152
quantum/send_string/send_string.h
Normal file
152
quantum/send_string/send_string.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* Copyright 2021
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup send_string
|
||||
*
|
||||
* Send String API. These functions allow you to create macros by typing out sequences of keystrokes.
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "progmem.h"
|
||||
#include "send_string_keycodes.h"
|
||||
|
||||
// Look-Up Tables (LUTs) to convert ASCII character to keycode sequence.
|
||||
extern const uint8_t ascii_to_shift_lut[16];
|
||||
extern const uint8_t ascii_to_altgr_lut[16];
|
||||
extern const uint8_t ascii_to_dead_lut[16];
|
||||
extern const uint8_t ascii_to_keycode_lut[128];
|
||||
|
||||
// clang-format off
|
||||
#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \
|
||||
( ((a) ? 1 : 0) << 0 \
|
||||
| ((b) ? 1 : 0) << 1 \
|
||||
| ((c) ? 1 : 0) << 2 \
|
||||
| ((d) ? 1 : 0) << 3 \
|
||||
| ((e) ? 1 : 0) << 4 \
|
||||
| ((f) ? 1 : 0) << 5 \
|
||||
| ((g) ? 1 : 0) << 6 \
|
||||
| ((h) ? 1 : 0) << 7 )
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* \brief Type out a string of ASCII characters.
|
||||
*
|
||||
* This function simply calls `send_string_with_delay(string, 0)`.
|
||||
*
|
||||
* Most keycodes from the basic keycode range are also supported by way of a special sequence - see `send_string_keycodes.h`.
|
||||
*
|
||||
* \param string The string to type out.
|
||||
*/
|
||||
void send_string(const char *string);
|
||||
|
||||
/**
|
||||
* \brief Type out a string of ASCII characters, with a delay between each character.
|
||||
*
|
||||
* \param string The string to type out.
|
||||
* \param interval The amount of time, in milliseconds, to wait before typing the next character.
|
||||
*/
|
||||
void send_string_with_delay(const char *string, uint8_t interval);
|
||||
|
||||
/**
|
||||
* \brief Type out an ASCII character.
|
||||
*
|
||||
* \param ascii_code The character to type.
|
||||
*/
|
||||
void send_char(char ascii_code);
|
||||
|
||||
/**
|
||||
* \brief Type out an eight digit (unsigned 32-bit) hexadecimal value.
|
||||
*
|
||||
* The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`.
|
||||
*
|
||||
* \param number The value to type, from 0 to 4,294,967,295.
|
||||
*/
|
||||
void send_dword(uint32_t number);
|
||||
|
||||
/**
|
||||
* \brief Type out a four digit (unsigned 16-bit) hexadecimal value.
|
||||
*
|
||||
* The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`.
|
||||
*
|
||||
* \param number The value to type, from 0 to 65,535.
|
||||
*/
|
||||
void send_word(uint16_t number);
|
||||
|
||||
/**
|
||||
* \brief Type out a two digit (8-bit) hexadecimal value.
|
||||
*
|
||||
* The format is `[0-9a-f]{2}`, eg. `00` through `ff`.
|
||||
*
|
||||
* \param number The value to type, from 0 to 255.
|
||||
*/
|
||||
void send_byte(uint8_t number);
|
||||
|
||||
/**
|
||||
* \brief Type out a single hexadecimal digit.
|
||||
*
|
||||
* The format is `[0-9a-f]{1}`, eg. `0` through `f`.
|
||||
*
|
||||
* \param number The value to type, from 0 to 15.
|
||||
*/
|
||||
void send_nibble(uint8_t number);
|
||||
|
||||
/**
|
||||
* \brief Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`.
|
||||
*/
|
||||
void tap_random_base64(void);
|
||||
|
||||
#if defined(__AVR__) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* \brief Type out a PROGMEM string of ASCII characters.
|
||||
*
|
||||
* On ARM devices, this function is simply an alias for send_string_with_delay(string, 0).
|
||||
*
|
||||
* \param string The string to type out.
|
||||
*/
|
||||
void send_string_P(const char *string);
|
||||
|
||||
/**
|
||||
* \brief Type out a PROGMEM string of ASCII characters, with a delay between each character.
|
||||
*
|
||||
* On ARM devices, this function is simply an alias for send_string_with_delay(string, interval).
|
||||
*
|
||||
* \param string The string to type out.
|
||||
* \param interval The amount of time, in milliseconds, to wait before typing the next character.
|
||||
*/
|
||||
void send_string_with_delay_P(const char *string, uint8_t interval);
|
||||
#else
|
||||
# define send_string_P(string) send_string_with_delay(string, 0)
|
||||
# define send_string_with_delay_P(string, interval) send_string_with_delay(string, interval)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Shortcut macro for send_string_with_delay_P(PSTR(string), 0).
|
||||
*
|
||||
* On ARM devices, this define evaluates to send_string_with_delay(string, 0).
|
||||
*/
|
||||
#define SEND_STRING(string) send_string_with_delay_P(PSTR(string), 0)
|
||||
|
||||
/**
|
||||
* \brief Shortcut macro for send_string_with_delay_P(PSTR(string), interval).
|
||||
*
|
||||
* On ARM devices, this define evaluates to send_string_with_delay(string, interval).
|
||||
*/
|
||||
#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval)
|
||||
|
||||
/** \} */
|
||||
436
quantum/send_string/send_string_keycodes.h
Normal file
436
quantum/send_string/send_string_keycodes.h
Normal file
@@ -0,0 +1,436 @@
|
||||
/* Copyright 2019
|
||||
*
|
||||
* 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
|
||||
|
||||
// clang-format off
|
||||
|
||||
/* Punctuation */
|
||||
#define X_ENT X_ENTER
|
||||
#define X_ESC X_ESCAPE
|
||||
#define X_BSPC X_BSPACE
|
||||
#define X_SPC X_SPACE
|
||||
#define X_MINS X_MINUS
|
||||
#define X_EQL X_EQUAL
|
||||
#define X_LBRC X_LBRACKET
|
||||
#define X_RBRC X_RBRACKET
|
||||
#define X_BSLS X_BSLASH
|
||||
#define X_NUHS X_NONUS_HASH
|
||||
#define X_SCLN X_SCOLON
|
||||
#define X_QUOT X_QUOTE
|
||||
#define X_GRV X_GRAVE
|
||||
#define X_COMM X_COMMA
|
||||
#define X_SLSH X_SLASH
|
||||
#define X_NUBS X_NONUS_BSLASH
|
||||
|
||||
/* Lock Keys */
|
||||
#define X_CLCK X_CAPSLOCK
|
||||
#define X_CAPS X_CAPSLOCK
|
||||
#define X_SLCK X_SCROLLLOCK
|
||||
#define X_NLCK X_NUMLOCK
|
||||
#define X_LCAP X_LOCKING_CAPS
|
||||
#define X_LNUM X_LOCKING_NUM
|
||||
#define X_LSCR X_LOCKING_SCROLL
|
||||
|
||||
/* Commands */
|
||||
#define X_PSCR X_PSCREEN
|
||||
#define X_PAUS X_PAUSE
|
||||
#define X_BRK X_PAUSE
|
||||
#define X_INS X_INSERT
|
||||
#define X_DEL X_DELETE
|
||||
#define X_PGDN X_PGDOWN
|
||||
#define X_RGHT X_RIGHT
|
||||
#define X_APP X_APPLICATION
|
||||
#define X_EXEC X_EXECUTE
|
||||
#define X_SLCT X_SELECT
|
||||
#define X_AGIN X_AGAIN
|
||||
#define X_PSTE X_PASTE
|
||||
#define X_ERAS X_ALT_ERASE
|
||||
#define X_CLR X_CLEAR
|
||||
|
||||
/* Keypad */
|
||||
#define X_PSLS X_KP_SLASH
|
||||
#define X_PAST X_KP_ASTERISK
|
||||
#define X_PMNS X_KP_MINUS
|
||||
#define X_PPLS X_KP_PLUS
|
||||
#define X_PENT X_KP_ENTER
|
||||
#define X_P1 X_KP_1
|
||||
#define X_P2 X_KP_2
|
||||
#define X_P3 X_KP_3
|
||||
#define X_P4 X_KP_4
|
||||
#define X_P5 X_KP_5
|
||||
#define X_P6 X_KP_6
|
||||
#define X_P7 X_KP_7
|
||||
#define X_P8 X_KP_8
|
||||
#define X_P9 X_KP_9
|
||||
#define X_P0 X_KP_0
|
||||
#define X_PDOT X_KP_DOT
|
||||
#define X_PEQL X_KP_EQUAL
|
||||
#define X_PCMM X_KP_COMMA
|
||||
|
||||
/* Japanese specific */
|
||||
#define X_ZKHK X_GRAVE
|
||||
#define X_RO X_INT1
|
||||
#define X_KANA X_INT2
|
||||
#define X_JYEN X_INT3
|
||||
#define X_HENK X_INT4
|
||||
#define X_MHEN X_INT5
|
||||
|
||||
/* Korean specific */
|
||||
#define X_HAEN X_LANG1
|
||||
#define X_HANJ X_LANG2
|
||||
|
||||
/* Modifiers */
|
||||
#define X_LCTL X_LCTRL
|
||||
#define X_LSFT X_LSHIFT
|
||||
#define X_LOPT X_LALT
|
||||
#define X_LCMD X_LGUI
|
||||
#define X_LWIN X_LGUI
|
||||
#define X_RCTL X_RCTRL
|
||||
#define X_RSFT X_RSHIFT
|
||||
#define X_ALGR X_RALT
|
||||
#define X_ROPT X_RALT
|
||||
#define X_RCMD X_RGUI
|
||||
#define X_RWIN X_RGUI
|
||||
|
||||
/* Generic Desktop Page (0x01) */
|
||||
#define X_PWR X_SYSTEM_POWER
|
||||
#define X_SLEP X_SYSTEM_SLEEP
|
||||
#define X_WAKE X_SYSTEM_WAKE
|
||||
|
||||
/* Consumer Page (0x0C) */
|
||||
#define X_MUTE X_AUDIO_MUTE
|
||||
#define X_VOLU X_AUDIO_VOL_UP
|
||||
#define X_VOLD X_AUDIO_VOL_DOWN
|
||||
#define X_MNXT X_MEDIA_NEXT_TRACK
|
||||
#define X_MPRV X_MEDIA_PREV_TRACK
|
||||
#define X_MSTP X_MEDIA_STOP
|
||||
#define X_MPLY X_MEDIA_PLAY_PAUSE
|
||||
#define X_MSEL X_MEDIA_SELECT
|
||||
#define X_EJCT X_MEDIA_EJECT
|
||||
#define X_CALC X_CALCULATOR
|
||||
#define X_MYCM X_MY_COMPUTER
|
||||
#define X_WSCH X_WWW_SEARCH
|
||||
#define X_WHOM X_WWW_HOME
|
||||
#define X_WBAK X_WWW_BACK
|
||||
#define X_WFWD X_WWW_FORWARD
|
||||
#define X_WSTP X_WWW_STOP
|
||||
#define X_WREF X_WWW_REFRESH
|
||||
#define X_WFAV X_WWW_FAVORITES
|
||||
#define X_MFFD X_MEDIA_FAST_FORWARD
|
||||
#define X_MRWD X_MEDIA_REWIND
|
||||
#define X_BRIU X_BRIGHTNESS_UP
|
||||
#define X_BRID X_BRIGHTNESS_DOWN
|
||||
|
||||
/* System Specific */
|
||||
#define X_BRMU X_PAUSE
|
||||
#define X_BRMD X_SCROLLLOCK
|
||||
|
||||
/* Mouse Keys */
|
||||
#define X_MS_U X_MS_UP
|
||||
#define X_MS_D X_MS_DOWN
|
||||
#define X_MS_L X_MS_LEFT
|
||||
#define X_MS_R X_MS_RIGHT
|
||||
#define X_BTN1 X_MS_BTN1
|
||||
#define X_BTN2 X_MS_BTN2
|
||||
#define X_BTN3 X_MS_BTN3
|
||||
#define X_BTN4 X_MS_BTN4
|
||||
#define X_BTN5 X_MS_BTN5
|
||||
#define X_WH_U X_MS_WH_UP
|
||||
#define X_WH_D X_MS_WH_DOWN
|
||||
#define X_WH_L X_MS_WH_LEFT
|
||||
#define X_WH_R X_MS_WH_RIGHT
|
||||
#define X_ACL0 X_MS_ACCEL0
|
||||
#define X_ACL1 X_MS_ACCEL1
|
||||
#define X_ACL2 X_MS_ACCEL2
|
||||
|
||||
/* Keyboard/Keypad Page (0x07) */
|
||||
#define X_A 04
|
||||
#define X_B 05
|
||||
#define X_C 06
|
||||
#define X_D 07
|
||||
#define X_E 08
|
||||
#define X_F 09
|
||||
#define X_G 0a
|
||||
#define X_H 0b
|
||||
#define X_I 0c
|
||||
#define X_J 0d
|
||||
#define X_K 0e
|
||||
#define X_L 0f
|
||||
#define X_M 10
|
||||
#define X_N 11
|
||||
#define X_O 12
|
||||
#define X_P 13
|
||||
#define X_Q 14
|
||||
#define X_R 15
|
||||
#define X_S 16
|
||||
#define X_T 17
|
||||
#define X_U 18
|
||||
#define X_V 19
|
||||
#define X_W 1a
|
||||
#define X_X 1b
|
||||
#define X_Y 1c
|
||||
#define X_Z 1d
|
||||
#define X_1 1e
|
||||
#define X_2 1f
|
||||
#define X_3 20
|
||||
#define X_4 21
|
||||
#define X_5 22
|
||||
#define X_6 23
|
||||
#define X_7 24
|
||||
#define X_8 25
|
||||
#define X_9 26
|
||||
#define X_0 27
|
||||
#define X_ENTER 28
|
||||
#define X_ESCAPE 29
|
||||
#define X_BSPACE 2a
|
||||
#define X_TAB 2b
|
||||
#define X_SPACE 2c
|
||||
#define X_MINUS 2d
|
||||
#define X_EQUAL 2e
|
||||
#define X_LBRACKET 2f
|
||||
#define X_RBRACKET 30
|
||||
#define X_BSLASH 31
|
||||
#define X_NONUS_HASH 32
|
||||
#define X_SCOLON 33
|
||||
#define X_QUOTE 34
|
||||
#define X_GRAVE 35
|
||||
#define X_COMMA 36
|
||||
#define X_DOT 37
|
||||
#define X_SLASH 38
|
||||
#define X_CAPSLOCK 39
|
||||
#define X_F1 3a
|
||||
#define X_F2 3b
|
||||
#define X_F3 3c
|
||||
#define X_F4 3d
|
||||
#define X_F5 3e
|
||||
#define X_F6 3f
|
||||
#define X_F7 40
|
||||
#define X_F8 41
|
||||
#define X_F9 42
|
||||
#define X_F10 43
|
||||
#define X_F11 44
|
||||
#define X_F12 45
|
||||
#define X_PSCREEN 46
|
||||
#define X_SCROLLLOCK 47
|
||||
#define X_PAUSE 48
|
||||
#define X_INSERT 49
|
||||
#define X_HOME 4a
|
||||
#define X_PGUP 4b
|
||||
#define X_DELETE 4c
|
||||
#define X_END 4d
|
||||
#define X_PGDOWN 4e
|
||||
#define X_RIGHT 4f
|
||||
#define X_LEFT 50
|
||||
#define X_DOWN 51
|
||||
#define X_UP 52
|
||||
#define X_NUMLOCK 53
|
||||
#define X_KP_SLASH 54
|
||||
#define X_KP_ASTERISK 55
|
||||
#define X_KP_MINUS 56
|
||||
#define X_KP_PLUS 57
|
||||
#define X_KP_ENTER 58
|
||||
#define X_KP_1 59
|
||||
#define X_KP_2 5a
|
||||
#define X_KP_3 5b
|
||||
#define X_KP_4 5c
|
||||
#define X_KP_5 5d
|
||||
#define X_KP_6 5e
|
||||
#define X_KP_7 5f
|
||||
#define X_KP_8 60
|
||||
#define X_KP_9 61
|
||||
#define X_KP_0 62
|
||||
#define X_KP_DOT 63
|
||||
#define X_NONUS_BSLASH 64
|
||||
#define X_APPLICATION 65
|
||||
#define X_POWER 66
|
||||
#define X_KP_EQUAL 67
|
||||
#define X_F13 68
|
||||
#define X_F14 69
|
||||
#define X_F15 6a
|
||||
#define X_F16 6b
|
||||
#define X_F17 6c
|
||||
#define X_F18 6d
|
||||
#define X_F19 6e
|
||||
#define X_F20 6f
|
||||
#define X_F21 70
|
||||
#define X_F22 71
|
||||
#define X_F23 72
|
||||
#define X_F24 73
|
||||
#define X_EXECUTE 74
|
||||
#define X_HELP 75
|
||||
#define X_MENU 76
|
||||
#define X_SELECT 77
|
||||
#define X_STOP 78
|
||||
#define X_AGAIN 79
|
||||
#define X_UNDO 7a
|
||||
#define X_CUT 7b
|
||||
#define X_COPY 7c
|
||||
#define X_PASTE 7d
|
||||
#define X_FIND 7e
|
||||
#define X__MUTE 7f
|
||||
#define X__VOLUP 80
|
||||
#define X__VOLDOWN 81
|
||||
#define X_LOCKING_CAPS 82
|
||||
#define X_LOCKING_NUM 83
|
||||
#define X_LOCKING_SCROLL 84
|
||||
#define X_KP_COMMA 85
|
||||
#define X_KP_EQUAL_AS400 86
|
||||
#define X_INT1 87
|
||||
#define X_INT2 88
|
||||
#define X_INT3 89
|
||||
#define X_INT4 8a
|
||||
#define X_INT5 8b
|
||||
#define X_INT6 8c
|
||||
#define X_INT7 8d
|
||||
#define X_INT8 8e
|
||||
#define X_INT9 8f
|
||||
#define X_LANG1 90
|
||||
#define X_LANG2 91
|
||||
#define X_LANG3 92
|
||||
#define X_LANG4 93
|
||||
#define X_LANG5 94
|
||||
#define X_LANG6 95
|
||||
#define X_LANG7 96
|
||||
#define X_LANG8 97
|
||||
#define X_LANG9 98
|
||||
#define X_ALT_ERASE 99
|
||||
#define X_SYSREQ 9a
|
||||
#define X_CANCEL 9b
|
||||
#define X_CLEAR 9c
|
||||
#define X_PRIOR 9d
|
||||
#define X_RETURN 9e
|
||||
#define X_SEPARATOR 9f
|
||||
#define X_OUT a0
|
||||
#define X_OPER a1
|
||||
#define X_CLEAR_AGAIN a2
|
||||
#define X_CRSEL a3
|
||||
#define X_EXSEL a4
|
||||
|
||||
/* Modifiers */
|
||||
#define X_LCTRL e0
|
||||
#define X_LSHIFT e1
|
||||
#define X_LALT e2
|
||||
#define X_LGUI e3
|
||||
#define X_RCTRL e4
|
||||
#define X_RSHIFT e5
|
||||
#define X_RALT e6
|
||||
#define X_RGUI e7
|
||||
|
||||
/* Media and Function keys */
|
||||
/* Generic Desktop Page (0x01) */
|
||||
#define X_SYSTEM_POWER a5
|
||||
#define X_SYSTEM_SLEEP a6
|
||||
#define X_SYSTEM_WAKE a7
|
||||
|
||||
/* Consumer Page (0x0C) */
|
||||
#define X_AUDIO_MUTE a8
|
||||
#define X_AUDIO_VOL_UP a9
|
||||
#define X_AUDIO_VOL_DOWN aa
|
||||
#define X_MEDIA_NEXT_TRACK ab
|
||||
#define X_MEDIA_PREV_TRACK ac
|
||||
#define X_MEDIA_STOP ad
|
||||
#define X_MEDIA_PLAY_PAUSE ae
|
||||
#define X_MEDIA_SELECT af
|
||||
#define X_MEDIA_EJECT b0
|
||||
#define X_MAIL b1
|
||||
#define X_CALCULATOR b2
|
||||
#define X_MY_COMPUTER b3
|
||||
#define X_WWW_SEARCH b4
|
||||
#define X_WWW_HOME b5
|
||||
#define X_WWW_BACK b6
|
||||
#define X_WWW_FORWARD b7
|
||||
#define X_WWW_STOP b8
|
||||
#define X_WWW_REFRESH b9
|
||||
#define X_WWW_FAVORITES ba
|
||||
#define X_MEDIA_FAST_FORWARD bb
|
||||
#define X_MEDIA_REWIND bc
|
||||
#define X_BRIGHTNESS_UP bd
|
||||
#define X_BRIGHTNESS_DOWN be
|
||||
|
||||
/* Mouse Buttons (unallocated range in HID spec) */
|
||||
#ifdef VIA_ENABLE
|
||||
#define X_MS_UP f0
|
||||
#define X_MS_DOWN f1
|
||||
#define X_MS_LEFT f2
|
||||
#define X_MS_RIGHT f3
|
||||
#define X_MS_BTN1 f4
|
||||
#define X_MS_BTN2 f5
|
||||
#define X_MS_BTN3 f6
|
||||
#define X_MS_BTN4 f7
|
||||
#define X_MS_BTN5 f8
|
||||
#define X_MS_BTN6 f8
|
||||
#define X_MS_BTN7 f8
|
||||
#define X_MS_BTN8 f8
|
||||
#else
|
||||
#define X_MS_UP ed
|
||||
#define X_MS_DOWN ee
|
||||
#define X_MS_LEFT ef
|
||||
#define X_MS_RIGHT f0
|
||||
#define X_MS_BTN1 f1
|
||||
#define X_MS_BTN2 f2
|
||||
#define X_MS_BTN3 f3
|
||||
#define X_MS_BTN4 f4
|
||||
#define X_MS_BTN5 f5
|
||||
#define X_MS_BTN6 f6
|
||||
#define X_MS_BTN7 f7
|
||||
#define X_MS_BTN8 f8
|
||||
#endif
|
||||
#define X_MS_WH_UP f9
|
||||
#define X_MS_WH_DOWN fa
|
||||
#define X_MS_WH_LEFT fb
|
||||
#define X_MS_WH_RIGHT fc
|
||||
#define X_MS_ACCEL0 fd
|
||||
#define X_MS_ACCEL1 fe
|
||||
#define X_MS_ACCEL2 ff
|
||||
|
||||
// Send string macros
|
||||
#define STRINGIZE(z) #z
|
||||
#define ADD_SLASH_X(y) STRINGIZE(\x##y)
|
||||
#define SYMBOL_STR(x) ADD_SLASH_X(x)
|
||||
|
||||
#define SS_QMK_PREFIX 1
|
||||
|
||||
#define SS_TAP_CODE 1
|
||||
#define SS_DOWN_CODE 2
|
||||
#define SS_UP_CODE 3
|
||||
#define SS_DELAY_CODE 4
|
||||
|
||||
#define SS_TAP(keycode) "\1\1" SYMBOL_STR(keycode)
|
||||
#define SS_DOWN(keycode) "\1\2" SYMBOL_STR(keycode)
|
||||
#define SS_UP(keycode) "\1\3" SYMBOL_STR(keycode)
|
||||
#define SS_DELAY(msecs) "\1\4" STRINGIZE(msecs) "|"
|
||||
|
||||
// `string` arguments must not be parenthesized
|
||||
#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL)
|
||||
#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT)
|
||||
#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT)
|
||||
#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI)
|
||||
#define SS_LOPT(string) SS_LALT(string)
|
||||
#define SS_LCMD(string) SS_LGUI(string)
|
||||
#define SS_LWIN(string) SS_LGUI(string)
|
||||
|
||||
#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL)
|
||||
#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT)
|
||||
#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT)
|
||||
#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI)
|
||||
#define SS_ALGR(string) SS_RALT(string)
|
||||
#define SS_ROPT(string) SS_RALT(string)
|
||||
#define SS_RCMD(string) SS_RGUI(string)
|
||||
#define SS_RWIN(string) SS_RGUI(string)
|
||||
|
||||
// DEPRECATED
|
||||
#define SS_LCTRL(string) SS_LCTL(string)
|
||||
@@ -1,505 +0,0 @@
|
||||
/* Copyright 2019
|
||||
*
|
||||
* 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
|
||||
|
||||
// clang-format off
|
||||
|
||||
/* Punctuation */
|
||||
#define X_ENT X_ENTER
|
||||
#define X_ESC X_ESCAPE
|
||||
#define X_BSPC X_BACKSPACE
|
||||
#define X_SPC X_SPACE
|
||||
#define X_MINS X_MINUS
|
||||
#define X_EQL X_EQUAL
|
||||
#define X_LBRC X_LEFT_BRACKET
|
||||
#define X_RBRC X_RIGHT_BRACKET
|
||||
#define X_BSLS X_BACKSLASH
|
||||
#define X_NUHS X_NONUS_HASH
|
||||
#define X_SCLN X_SEMICOLON
|
||||
#define X_QUOT X_QUOTE
|
||||
#define X_GRV X_GRAVE
|
||||
#define X_COMM X_COMMA
|
||||
#define X_SLSH X_SLASH
|
||||
#define X_NUBS X_NONUS_BACKSLASH
|
||||
|
||||
/* Lock Keys */
|
||||
#define X_CAPS X_CAPS_LOCK
|
||||
#define X_SCRL X_SCROLL_LOCK
|
||||
#define X_NUM X_NUM_LOCK
|
||||
#define X_LCAP X_LOCKING_CAPS_LOCK
|
||||
#define X_LNUM X_LOCKING_NUM_LOCK
|
||||
#define X_LSCR X_LOCKING_SCROLL_LOCK
|
||||
|
||||
/* Commands */
|
||||
#define X_PSCR X_PRINT_SCREEN
|
||||
#define X_PAUS X_PAUSE
|
||||
#define X_BRK X_PAUSE
|
||||
#define X_INS X_INSERT
|
||||
#define X_PGUP X_PAGE_UP
|
||||
#define X_DEL X_DELETE
|
||||
#define X_PGDN X_PAGE_DOWN
|
||||
#define X_RGHT X_RIGHT
|
||||
#define X_APP X_APPLICATION
|
||||
#define X_EXEC X_EXECUTE
|
||||
#define X_SLCT X_SELECT
|
||||
#define X_AGIN X_AGAIN
|
||||
#define X_PSTE X_PASTE
|
||||
#define X_ERAS X_ALTERNATE_ERASE
|
||||
#define X_SYRQ X_SYSTEM_REQUEST
|
||||
#define X_CNCL X_CANCEL
|
||||
#define X_CLR X_CLEAR
|
||||
#define X_PRIR X_PRIOR
|
||||
#define X_RETN X_RETURN
|
||||
#define X_SEPR X_SEPARATOR
|
||||
#define X_CLAG X_CLEAR_AGAIN
|
||||
#define X_CRSL X_CRSEL
|
||||
#define X_EXSL X_EXSEL
|
||||
|
||||
/* Keypad */
|
||||
#define X_PSLS X_KP_SLASH
|
||||
#define X_PAST X_KP_ASTERISK
|
||||
#define X_PMNS X_KP_MINUS
|
||||
#define X_PPLS X_KP_PLUS
|
||||
#define X_PENT X_KP_ENTER
|
||||
#define X_P1 X_KP_1
|
||||
#define X_P2 X_KP_2
|
||||
#define X_P3 X_KP_3
|
||||
#define X_P4 X_KP_4
|
||||
#define X_P5 X_KP_5
|
||||
#define X_P6 X_KP_6
|
||||
#define X_P7 X_KP_7
|
||||
#define X_P8 X_KP_8
|
||||
#define X_P9 X_KP_9
|
||||
#define X_P0 X_KP_0
|
||||
#define X_PDOT X_KP_DOT
|
||||
#define X_PEQL X_KP_EQUAL
|
||||
#define X_PCMM X_KP_COMMA
|
||||
|
||||
/* Language Specific */
|
||||
#define X_INT1 X_INTERNATIONAL_1
|
||||
#define X_INT2 X_INTERNATIONAL_2
|
||||
#define X_INT3 X_INTERNATIONAL_3
|
||||
#define X_INT4 X_INTERNATIONAL_4
|
||||
#define X_INT5 X_INTERNATIONAL_5
|
||||
#define X_INT6 X_INTERNATIONAL_6
|
||||
#define X_INT7 X_INTERNATIONAL_7
|
||||
#define X_INT8 X_INTERNATIONAL_8
|
||||
#define X_INT9 X_INTERNATIONAL_9
|
||||
#define X_LNG1 X_LANGUAGE_1
|
||||
#define X_LNG2 X_LANGUAGE_2
|
||||
#define X_LNG3 X_LANGUAGE_3
|
||||
#define X_LNG4 X_LANGUAGE_4
|
||||
#define X_LNG5 X_LANGUAGE_5
|
||||
#define X_LNG6 X_LANGUAGE_6
|
||||
#define X_LNG7 X_LANGUAGE_7
|
||||
#define X_LNG8 X_LANGUAGE_8
|
||||
#define X_LNG9 X_LANGUAGE_9
|
||||
|
||||
/* Modifiers */
|
||||
#define X_LCTL X_LEFT_CTRL
|
||||
#define X_LSFT X_LEFT_SHIFT
|
||||
#define X_LALT X_LEFT_ALT
|
||||
#define X_LOPT X_LEFT_ALT
|
||||
#define X_LGUI X_LEFT_GUI
|
||||
#define X_LCMD X_LEFT_GUI
|
||||
#define X_LWIN X_LEFT_GUI
|
||||
#define X_RCTL X_RIGHT_CTRL
|
||||
#define X_RSFT X_RIGHT_SHIFT
|
||||
#define X_RALT X_RIGHT_ALT
|
||||
#define X_ALGR X_RIGHT_ALT
|
||||
#define X_ROPT X_RIGHT_ALT
|
||||
#define X_RGUI X_RIGHT_GUI
|
||||
#define X_RCMD X_RIGHT_GUI
|
||||
#define X_RWIN X_RIGHT_GUI
|
||||
|
||||
/* Generic Desktop Page (0x01) */
|
||||
#define X_PWR X_SYSTEM_POWER
|
||||
#define X_SLEP X_SYSTEM_SLEEP
|
||||
#define X_WAKE X_SYSTEM_WAKE
|
||||
|
||||
/* Consumer Page (0x0C) */
|
||||
#define X_MUTE X_AUDIO_MUTE
|
||||
#define X_VOLU X_AUDIO_VOL_UP
|
||||
#define X_VOLD X_AUDIO_VOL_DOWN
|
||||
#define X_MNXT X_MEDIA_NEXT_TRACK
|
||||
#define X_MPRV X_MEDIA_PREV_TRACK
|
||||
#define X_MSTP X_MEDIA_STOP
|
||||
#define X_MPLY X_MEDIA_PLAY_PAUSE
|
||||
#define X_MSEL X_MEDIA_SELECT
|
||||
#define X_EJCT X_MEDIA_EJECT
|
||||
#define X_CALC X_CALCULATOR
|
||||
#define X_MYCM X_MY_COMPUTER
|
||||
#define X_WSCH X_WWW_SEARCH
|
||||
#define X_WHOM X_WWW_HOME
|
||||
#define X_WBAK X_WWW_BACK
|
||||
#define X_WFWD X_WWW_FORWARD
|
||||
#define X_WSTP X_WWW_STOP
|
||||
#define X_WREF X_WWW_REFRESH
|
||||
#define X_WFAV X_WWW_FAVORITES
|
||||
#define X_MFFD X_MEDIA_FAST_FORWARD
|
||||
#define X_MRWD X_MEDIA_REWIND
|
||||
#define X_BRIU X_BRIGHTNESS_UP
|
||||
#define X_BRID X_BRIGHTNESS_DOWN
|
||||
|
||||
/* System Specific */
|
||||
#define X_BRMU X_PAUSE
|
||||
#define X_BRMD X_SCROLL_LOCK
|
||||
|
||||
/* Mouse Keys */
|
||||
#define X_MS_U X_MS_UP
|
||||
#define X_MS_D X_MS_DOWN
|
||||
#define X_MS_L X_MS_LEFT
|
||||
#define X_MS_R X_MS_RIGHT
|
||||
#define X_BTN1 X_MS_BTN1
|
||||
#define X_BTN2 X_MS_BTN2
|
||||
#define X_BTN3 X_MS_BTN3
|
||||
#define X_BTN4 X_MS_BTN4
|
||||
#define X_BTN5 X_MS_BTN5
|
||||
#define X_BTN6 X_MS_BTN6
|
||||
#define X_BTN7 X_MS_BTN7
|
||||
#define X_BTN8 X_MS_BTN8
|
||||
#define X_WH_U X_MS_WH_UP
|
||||
#define X_WH_D X_MS_WH_DOWN
|
||||
#define X_WH_L X_MS_WH_LEFT
|
||||
#define X_WH_R X_MS_WH_RIGHT
|
||||
#define X_ACL0 X_MS_ACCEL0
|
||||
#define X_ACL1 X_MS_ACCEL1
|
||||
#define X_ACL2 X_MS_ACCEL2
|
||||
|
||||
/* Keyboard/Keypad Page (0x07) */
|
||||
#define X_A 04
|
||||
#define X_B 05
|
||||
#define X_C 06
|
||||
#define X_D 07
|
||||
#define X_E 08
|
||||
#define X_F 09
|
||||
#define X_G 0a
|
||||
#define X_H 0b
|
||||
#define X_I 0c
|
||||
#define X_J 0d
|
||||
#define X_K 0e
|
||||
#define X_L 0f
|
||||
#define X_M 10
|
||||
#define X_N 11
|
||||
#define X_O 12
|
||||
#define X_P 13
|
||||
#define X_Q 14
|
||||
#define X_R 15
|
||||
#define X_S 16
|
||||
#define X_T 17
|
||||
#define X_U 18
|
||||
#define X_V 19
|
||||
#define X_W 1a
|
||||
#define X_X 1b
|
||||
#define X_Y 1c
|
||||
#define X_Z 1d
|
||||
#define X_1 1e
|
||||
#define X_2 1f
|
||||
#define X_3 20
|
||||
#define X_4 21
|
||||
#define X_5 22
|
||||
#define X_6 23
|
||||
#define X_7 24
|
||||
#define X_8 25
|
||||
#define X_9 26
|
||||
#define X_0 27
|
||||
#define X_ENTER 28
|
||||
#define X_ESCAPE 29
|
||||
#define X_BACKSPACE 2a
|
||||
#define X_TAB 2b
|
||||
#define X_SPACE 2c
|
||||
#define X_MINUS 2d
|
||||
#define X_EQUAL 2e
|
||||
#define X_LEFT_BRACKET 2f
|
||||
#define X_RIGHT_BRACKET 30
|
||||
#define X_BACKSLASH 31
|
||||
#define X_NONUS_HASH 32
|
||||
#define X_SEMICOLON 33
|
||||
#define X_QUOTE 34
|
||||
#define X_GRAVE 35
|
||||
#define X_COMMA 36
|
||||
#define X_DOT 37
|
||||
#define X_SLASH 38
|
||||
#define X_CAPS_LOCK 39
|
||||
#define X_F1 3a
|
||||
#define X_F2 3b
|
||||
#define X_F3 3c
|
||||
#define X_F4 3d
|
||||
#define X_F5 3e
|
||||
#define X_F6 3f
|
||||
#define X_F7 40
|
||||
#define X_F8 41
|
||||
#define X_F9 42
|
||||
#define X_F10 43
|
||||
#define X_F11 44
|
||||
#define X_F12 45
|
||||
#define X_PRINT_SCREEN 46
|
||||
#define X_SCROLL_LOCK 47
|
||||
#define X_PAUSE 48
|
||||
#define X_INSERT 49
|
||||
#define X_HOME 4a
|
||||
#define X_PAGE_UP 4b
|
||||
#define X_DELETE 4c
|
||||
#define X_END 4d
|
||||
#define X_PAGE_DOWN 4e
|
||||
#define X_RIGHT 4f
|
||||
#define X_LEFT 50
|
||||
#define X_DOWN 51
|
||||
#define X_UP 52
|
||||
#define X_NUM_LOCK 53
|
||||
#define X_KP_SLASH 54
|
||||
#define X_KP_ASTERISK 55
|
||||
#define X_KP_MINUS 56
|
||||
#define X_KP_PLUS 57
|
||||
#define X_KP_ENTER 58
|
||||
#define X_KP_1 59
|
||||
#define X_KP_2 5a
|
||||
#define X_KP_3 5b
|
||||
#define X_KP_4 5c
|
||||
#define X_KP_5 5d
|
||||
#define X_KP_6 5e
|
||||
#define X_KP_7 5f
|
||||
#define X_KP_8 60
|
||||
#define X_KP_9 61
|
||||
#define X_KP_0 62
|
||||
#define X_KP_DOT 63
|
||||
#define X_NONUS_BACKSLASH 64
|
||||
#define X_APPLICATION 65
|
||||
#define X_KB_POWER 66
|
||||
#define X_KP_EQUAL 67
|
||||
#define X_F13 68
|
||||
#define X_F14 69
|
||||
#define X_F15 6a
|
||||
#define X_F16 6b
|
||||
#define X_F17 6c
|
||||
#define X_F18 6d
|
||||
#define X_F19 6e
|
||||
#define X_F20 6f
|
||||
#define X_F21 70
|
||||
#define X_F22 71
|
||||
#define X_F23 72
|
||||
#define X_F24 73
|
||||
#define X_EXECUTE 74
|
||||
#define X_HELP 75
|
||||
#define X_MENU 76
|
||||
#define X_SELECT 77
|
||||
#define X_STOP 78
|
||||
#define X_AGAIN 79
|
||||
#define X_UNDO 7a
|
||||
#define X_CUT 7b
|
||||
#define X_COPY 7c
|
||||
#define X_PASTE 7d
|
||||
#define X_FIND 7e
|
||||
#define X_KB_MUTE 7f
|
||||
#define X_KB_VOLUME_UP 80
|
||||
#define X_KB_VOLUME_DOWN 81
|
||||
#define X_LOCKING_CAPS_LOCK 82
|
||||
#define X_LOCKING_NUM_LOCK 83
|
||||
#define X_LOCKING_SCROLL_LOCK 84
|
||||
#define X_KP_COMMA 85
|
||||
#define X_KP_EQUAL_AS400 86
|
||||
#define X_INTERNATIONAL_1 87
|
||||
#define X_INTERNATIONAL_2 88
|
||||
#define X_INTERNATIONAL_3 89
|
||||
#define X_INTERNATIONAL_4 8a
|
||||
#define X_INTERNATIONAL_5 8b
|
||||
#define X_INTERNATIONAL_6 8c
|
||||
#define X_INTERNATIONAL_7 8d
|
||||
#define X_INTERNATIONAL_8 8e
|
||||
#define X_INTERNATIONAL_9 8f
|
||||
#define X_LANGUAGE_1 90
|
||||
#define X_LANGUAGE_2 91
|
||||
#define X_LANGUAGE_3 92
|
||||
#define X_LANGUAGE_4 93
|
||||
#define X_LANGUAGE_5 94
|
||||
#define X_LANGUAGE_6 95
|
||||
#define X_LANGUAGE_7 96
|
||||
#define X_LANGUAGE_8 97
|
||||
#define X_LANGUAGE_9 98
|
||||
#define X_ALTERNATE_ERASE 99
|
||||
#define X_SYSTEM_REQUEST 9a
|
||||
#define X_CANCEL 9b
|
||||
#define X_CLEAR 9c
|
||||
#define X_PRIOR 9d
|
||||
#define X_RETURN 9e
|
||||
#define X_SEPARATOR 9f
|
||||
#define X_OUT a0
|
||||
#define X_OPER a1
|
||||
#define X_CLEAR_AGAIN a2
|
||||
#define X_CRSEL a3
|
||||
#define X_EXSEL a4
|
||||
|
||||
/* Modifiers */
|
||||
#define X_LEFT_CTRL e0
|
||||
#define X_LEFT_SHIFT e1
|
||||
#define X_LEFT_ALT e2
|
||||
#define X_LEFT_GUI e3
|
||||
#define X_RIGHT_CTRL e4
|
||||
#define X_RIGHT_SHIFT e5
|
||||
#define X_RIGHT_ALT e6
|
||||
#define X_RIGHT_GUI e7
|
||||
|
||||
/* Media and Function keys */
|
||||
/* Generic Desktop Page (0x01) */
|
||||
#define X_SYSTEM_POWER a5
|
||||
#define X_SYSTEM_SLEEP a6
|
||||
#define X_SYSTEM_WAKE a7
|
||||
|
||||
/* Consumer Page (0x0C) */
|
||||
#define X_AUDIO_MUTE a8
|
||||
#define X_AUDIO_VOL_UP a9
|
||||
#define X_AUDIO_VOL_DOWN aa
|
||||
#define X_MEDIA_NEXT_TRACK ab
|
||||
#define X_MEDIA_PREV_TRACK ac
|
||||
#define X_MEDIA_STOP ad
|
||||
#define X_MEDIA_PLAY_PAUSE ae
|
||||
#define X_MEDIA_SELECT af
|
||||
#define X_MEDIA_EJECT b0
|
||||
#define X_MAIL b1
|
||||
#define X_CALCULATOR b2
|
||||
#define X_MY_COMPUTER b3
|
||||
#define X_WWW_SEARCH b4
|
||||
#define X_WWW_HOME b5
|
||||
#define X_WWW_BACK b6
|
||||
#define X_WWW_FORWARD b7
|
||||
#define X_WWW_STOP b8
|
||||
#define X_WWW_REFRESH b9
|
||||
#define X_WWW_FAVORITES ba
|
||||
#define X_MEDIA_FAST_FORWARD bb
|
||||
#define X_MEDIA_REWIND bc
|
||||
#define X_BRIGHTNESS_UP bd
|
||||
#define X_BRIGHTNESS_DOWN be
|
||||
|
||||
/* Mouse Buttons (unallocated range in HID spec) */
|
||||
#ifdef VIA_ENABLE
|
||||
#define X_MS_UP f0
|
||||
#define X_MS_DOWN f1
|
||||
#define X_MS_LEFT f2
|
||||
#define X_MS_RIGHT f3
|
||||
#define X_MS_BTN1 f4
|
||||
#define X_MS_BTN2 f5
|
||||
#define X_MS_BTN3 f6
|
||||
#define X_MS_BTN4 f7
|
||||
#define X_MS_BTN5 f8
|
||||
#define X_MS_BTN6 f8
|
||||
#define X_MS_BTN7 f8
|
||||
#define X_MS_BTN8 f8
|
||||
#else
|
||||
#define X_MS_UP ed
|
||||
#define X_MS_DOWN ee
|
||||
#define X_MS_LEFT ef
|
||||
#define X_MS_RIGHT f0
|
||||
#define X_MS_BTN1 f1
|
||||
#define X_MS_BTN2 f2
|
||||
#define X_MS_BTN3 f3
|
||||
#define X_MS_BTN4 f4
|
||||
#define X_MS_BTN5 f5
|
||||
#define X_MS_BTN6 f6
|
||||
#define X_MS_BTN7 f7
|
||||
#define X_MS_BTN8 f8
|
||||
#endif
|
||||
#define X_MS_WH_UP f9
|
||||
#define X_MS_WH_DOWN fa
|
||||
#define X_MS_WH_LEFT fb
|
||||
#define X_MS_WH_RIGHT fc
|
||||
#define X_MS_ACCEL0 fd
|
||||
#define X_MS_ACCEL1 fe
|
||||
#define X_MS_ACCEL2 ff
|
||||
|
||||
// Send string macros
|
||||
#define STRINGIZE(z) #z
|
||||
#define ADD_SLASH_X(y) STRINGIZE(\x##y)
|
||||
#define SYMBOL_STR(x) ADD_SLASH_X(x)
|
||||
|
||||
#define SS_QMK_PREFIX 1
|
||||
|
||||
#define SS_TAP_CODE 1
|
||||
#define SS_DOWN_CODE 2
|
||||
#define SS_UP_CODE 3
|
||||
#define SS_DELAY_CODE 4
|
||||
|
||||
#define SS_TAP(keycode) "\1\1" SYMBOL_STR(keycode)
|
||||
#define SS_DOWN(keycode) "\1\2" SYMBOL_STR(keycode)
|
||||
#define SS_UP(keycode) "\1\3" SYMBOL_STR(keycode)
|
||||
#define SS_DELAY(msecs) "\1\4" STRINGIZE(msecs) "|"
|
||||
|
||||
// `string` arguments must not be parenthesized
|
||||
#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL)
|
||||
#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT)
|
||||
#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT)
|
||||
#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI)
|
||||
#define SS_LCMD(string) SS_LGUI(string)
|
||||
#define SS_LWIN(string) SS_LGUI(string)
|
||||
|
||||
#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL)
|
||||
#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT)
|
||||
#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT)
|
||||
#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI)
|
||||
#define SS_ALGR(string) SS_RALT(string)
|
||||
#define SS_RCMD(string) SS_RGUI(string)
|
||||
#define SS_RWIN(string) SS_RGUI(string)
|
||||
|
||||
// DEPRECATED
|
||||
#define X_BSPACE X_BACKSPACE
|
||||
#define X_LBRACKET X_LEFT_BRACKET
|
||||
#define X_RBRACKET X_RIGHT_BRACKET
|
||||
#define X_BSLASH X_BACKSLASH
|
||||
#define X_SCOLON X_SEMICOLON
|
||||
#define X_CAPSLOCK X_CAPS_LOCK
|
||||
#define X_PSCREEN X_PRINT_SCREEN
|
||||
#define X_SCROLLLOCK X_SCROLL_LOCK
|
||||
#define X_PGDOWN X_PAGE_DOWN
|
||||
#define X_NUMLOCK X_NUM_LOCK
|
||||
#define X_NONUS_BSLASH X_NONUS_BACKSLASH
|
||||
#define X_POWER X_KB_POWER
|
||||
#define X__MUTE X_KB_MUTE
|
||||
#define X__VOLUP X_KB_VOLUME_UP
|
||||
#define X__VOLDOWN X_KB_VOLUME_DOWN
|
||||
#define X_LOCKING_CAPS X_LOCKING_CAPS_LOCK
|
||||
#define X_LOCKING_NUM X_LOCKING_NUM_LOCK
|
||||
#define X_LOCKING_SCROLL X_LOCKING_SCROLL_LOCK
|
||||
#define X_LANG1 X_LANGUAGE_1
|
||||
#define X_LANG2 X_LANGUAGE_2
|
||||
#define X_LANG3 X_LANGUAGE_3
|
||||
#define X_LANG4 X_LANGUAGE_4
|
||||
#define X_LANG5 X_LANGUAGE_5
|
||||
#define X_LANG6 X_LANGUAGE_6
|
||||
#define X_LANG7 X_LANGUAGE_7
|
||||
#define X_LANG8 X_LANGUAGE_8
|
||||
#define X_LANG9 X_LANGUAGE_9
|
||||
#define X_ALT_ERASE X_ALTERNATE_ERASE
|
||||
#define X_SYSREQ X_SYSTEM_REQUEST
|
||||
|
||||
#define X_LCTRL X_LEFT_CTRL
|
||||
#define X_LSHIFT X_LEFT_SHIFT
|
||||
#define X_RCTRL X_RIGHT_CTRL
|
||||
#define X_RSHIFT X_RIGHT_SHIFT
|
||||
|
||||
#define X_ZKHK X_GRAVE
|
||||
#define X_RO X_INTERNATIONAL_1
|
||||
#define X_KANA X_INTERNATIONAL_2
|
||||
#define X_JYEN X_INTERNATIONAL_3
|
||||
#define X_HENK X_INTERNATIONAL_4
|
||||
#define X_MHEN X_INTERNATIONAL_5
|
||||
#define X_HAEN X_LANGUAGE_1
|
||||
#define X_HANJ X_LANGUAGE_2
|
||||
|
||||
#define X_CLCK X_CAPS_LOCK
|
||||
#define X_SLCK X_SCROLL_LOCK
|
||||
#define X_NLCK X_NUM_LOCK
|
||||
|
||||
#define SS_LCTRL(string) SS_LCTL(string)
|
||||
@@ -57,8 +57,9 @@ static uint8_t connection_errors = 0;
|
||||
volatile bool isLeftHand = true;
|
||||
|
||||
#if defined(SPLIT_USB_DETECT)
|
||||
_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
|
||||
static bool usbIsActive(void) {
|
||||
for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
|
||||
for (uint16_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
|
||||
// This will return true if a USB connection has been established
|
||||
if (usb_connected_state()) {
|
||||
return true;
|
||||
@@ -93,7 +94,6 @@ static uint8_t peek_matrix_intersection(pin_t out_pin, pin_t in_pin) {
|
||||
__attribute__((weak)) bool is_keyboard_left(void) {
|
||||
#if defined(SPLIT_HAND_PIN)
|
||||
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
|
||||
setPinInput(SPLIT_HAND_PIN);
|
||||
# ifdef SPLIT_HAND_PIN_LOW_IS_LEFT
|
||||
return !readPin(SPLIT_HAND_PIN);
|
||||
# else
|
||||
@@ -132,6 +132,14 @@ __attribute__((weak)) bool is_keyboard_master(void) {
|
||||
|
||||
// this code runs before the keyboard is fully initialized
|
||||
void split_pre_init(void) {
|
||||
#if defined(SPLIT_HAND_PIN)
|
||||
setPinInput(SPLIT_HAND_PIN);
|
||||
wait_us(100);
|
||||
#elif defined(EE_HANDS)
|
||||
if (!eeconfig_is_enabled()) {
|
||||
eeconfig_init();
|
||||
}
|
||||
#endif
|
||||
isLeftHand = is_keyboard_left();
|
||||
|
||||
#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
|
||||
|
||||
@@ -694,7 +694,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
[PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback),
|
||||
[PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer),
|
||||
[EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback),
|
||||
[EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.payload.transaction_id, slave_rpc_exec_callback),
|
||||
[GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer),
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
};
|
||||
@@ -760,7 +760,8 @@ bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer
|
||||
if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false;
|
||||
|
||||
// Prepare the metadata block
|
||||
rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size};
|
||||
rpc_sync_info_t info = {.payload = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size}};
|
||||
info.checksum = crc8(&info.payload, sizeof(info.payload));
|
||||
|
||||
// Make sure the local side knows that we're not sending the full block of data
|
||||
split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size;
|
||||
@@ -791,18 +792,23 @@ void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *i
|
||||
// Ignore the args -- the `split_shmem` already has the info, we just need to act upon it.
|
||||
// We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime.
|
||||
|
||||
split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length;
|
||||
split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length;
|
||||
split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.payload.m2s_length;
|
||||
split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.payload.s2m_length;
|
||||
}
|
||||
|
||||
void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
|
||||
// We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed.
|
||||
// Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs.
|
||||
int8_t transaction_id = split_shmem->rpc_info.transaction_id;
|
||||
// As a safety precaution we check that the received payload matches its checksum first.
|
||||
if (crc8(&split_shmem->rpc_info.payload, sizeof(split_shmem->rpc_info.payload)) != split_shmem->rpc_info.checksum) {
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t transaction_id = split_shmem->rpc_info.payload.transaction_id;
|
||||
if (transaction_id < NUM_TOTAL_TRANSACTIONS) {
|
||||
split_transaction_desc_t *trans = &split_transaction_table[transaction_id];
|
||||
if (trans->slave_callback) {
|
||||
trans->slave_callback(split_shmem->rpc_info.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.s2m_length, split_shmem->rpc_s2m_buffer);
|
||||
trans->slave_callback(split_shmem->rpc_info.payload.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.payload.s2m_length, split_shmem->rpc_s2m_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user