Merge branch 'next' into vial

This commit is contained in:
Ilya Zhuravlev 2021-07-18 00:01:36 -04:00
commit 750b29fdb7
94 changed files with 1888 additions and 245 deletions

View File

@ -171,6 +171,11 @@ else
OPT_DEFS += -DEEPROM_DRIVER
COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
else ifeq ($(MCU_SERIES), STM32F4xx)
SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
OPT_DEFS += -DEEPROM_EMU_STM32F411xC
OPT_DEFS += -DSTM32_EEPROM_ENABLE
else
# This will effectively work the same as "transient" if not supported by the chip
SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
@ -453,6 +458,9 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
endif
ifeq ($(strip $(VIAL_ENABLE)), yes)
QMK_SETTINGS ?= yes
TAP_DANCE_ENABLE ?= yes
COMBO_ENABLE ?= yes
SRC += $(QUANTUM_DIR)/vial.c
EXTRAINCDIRS += $(KEYMAP_OUTPUT)
OPT_DEFS += -DVIAL_ENABLE -DNO_DEBUG
@ -471,11 +479,22 @@ ifeq ($(strip $(VIAL_ENCODERS_ENABLE)), yes)
OPT_DEFS += -DVIAL_ENCODERS_ENABLE
endif
ifeq ($(strip $(VIALRGB_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/vialrgb.c
OPT_DEFS += -DVIALRGB_ENABLE
endif
ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
OPT_DEFS += -DDYNAMIC_KEYMAP_ENABLE
SRC += $(QUANTUM_DIR)/dynamic_keymap.c
endif
ifeq ($(strip $(QMK_SETTINGS)), yes)
AUTO_SHIFT_ENABLE := yes
SRC += $(QUANTUM_DIR)/qmk_settings.c
OPT_DEFS += -DQMK_SETTINGS -DAUTO_SHIFT_NO_SETUP -DTAPPING_TERM_PER_KEY -DPERMISSIVE_HOLD_PER_KEY -DIGNORE_MOD_TAP_INTERRUPT_PER_KEY -DTAPPING_FORCE_HOLD_PER_KEY -DRETRO_TAPPING_PER_KEY
endif
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
OPT_DEFS += -DDIP_SWITCH_ENABLE
SRC += $(QUANTUM_DIR)/dip_switch.c

View File

@ -1,2 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no
COMBO_ENABLE = no

View File

@ -1,3 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
LTO_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no

View File

@ -1,3 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
LTO_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no

View File

@ -8,7 +8,7 @@ BOOTLOADER = stm32-dfu
# change yes to no to disable
#
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no # Mouse keys
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration

View File

@ -1,3 +1,6 @@
VIA_ENABLE = yes
LTO_ENABLE = yes
VIAL_ENABLE = yes
TAP_DANCE_ENABLE = no
COMBO_ENABLE = no
QMK_SETTINGS = no

View File

@ -1,3 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
VIAL_ENCODERS_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no

View File

@ -1,4 +1,4 @@
LTO_ENABLE = yes
VIA_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -1,4 +1,4 @@
LTO_ENABLE = yes
VIA_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -3,3 +3,4 @@ LTO_ENABLE = yes
VIAL_ENABLE = yes
CONSOLE_ENABLE = no
QMK_SETTINGS = no

View File

@ -1,2 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
TAP_DANCE_ENABLE = no
COMBO_ENABLE = no
QMK_SETTINGS = no

View File

@ -1,2 +1,5 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
TAP_DANCE_ENABLE = no
COMBO_ENABLE = no
QMK_SETTINGS = no

View File

@ -1,3 +1,4 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
LTO_ENABLE = yes
TAP_DANCE_ENABLE = no

View File

@ -1,3 +1,4 @@
VIA_ENABLE = yes
LTO_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -1,4 +1,5 @@
LTO_ENABLE = yes
VIA_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no

View File

@ -1,3 +1,5 @@
VIA_ENABLE = yes
LTO_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no
TAP_DANCE_ENABLE = no

View File

@ -1,2 +1,3 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -1,3 +1,4 @@
VIA_ENABLE = yes
LTO_ENABLE = yes
VIAL_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0000
#define DEVICE_VER 0x0001
#define MANUFACTURER Vial
#define PRODUCT STM32F401 example
/* key matrix size */
#define MATRIX_ROWS 2
#define MATRIX_COLS 2
#define MATRIX_ROW_PINS { B10, B11 }
#define MATRIX_COL_PINS { B1, B0 }
#define DIODE_DIRECTION COL2ROW
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* Use 1000hz polling */
#define USB_POLLING_INTERVAL_MS 1

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_1, KC_2,
KC_3, KC_4
),
[1] = LAYOUT(
KC_A, KC_B,
KC_C, KC_D
)
};

View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#define VIAL_KEYBOARD_UID {0xD8, 0x0B, 0x9A, 0xC5, 0x1E, 0xD3, 0xD2, 0xBE}
#define VIAL_UNLOCK_COMBO_ROWS { 0, 1 }
#define VIAL_UNLOCK_COMBO_COLS { 0, 1 }

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_1, KC_2,
KC_3, KC_4
),
[1] = LAYOUT(
KC_A, KC_B,
KC_C, KC_D
),
[2] = LAYOUT(
KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS
),
[3] = LAYOUT(
KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS
)
};

View File

@ -0,0 +1,2 @@
VIA_ENABLE = yes
VIAL_ENABLE = yes

View File

@ -0,0 +1,18 @@
{
"matrix": {
"rows": 2,
"cols": 2
},
"layouts": {
"keymap": [
[
"0,0",
"0,1"
],
[
"1,0",
"1,1"
]
]
}
}

View File

@ -0,0 +1,25 @@
# MCU name
MCU = STM32F401
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
MIDI_ENABLE = no # MIDI support
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no # Audio output on port C6
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
# Enter lower-power sleep mode when on the ChibiOS idle thread
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE

View File

@ -0,0 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "vial_stm32f401.h"

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "quantum.h"
#define LAYOUT( \
K00, K01, \
K10, K11 \
) { \
{ K00, K01 }, \
{ K10, K11 } \
}

View File

@ -1,4 +1,4 @@
VIA_ENABLE = yes
LTO_ENABLE = yes
VIAL_ENABLE = yes
QMK_SETTINGS = no

View File

@ -21,6 +21,7 @@
#include "quantum.h" // for send_string()
#include "dynamic_keymap.h"
#include "via.h" // for default VIA_EEPROM_ADDR_END
#include "dynamic_keymap_eeprom.h"
#ifdef VIAL_ENABLE
#include "vial.h"
@ -30,22 +31,6 @@
# define DYNAMIC_KEYMAP_MACRO_COUNT 16
#endif
// This is the default EEPROM max address to use for dynamic keymaps.
// The default is the ATmega32u4 EEPROM max address.
// Explicitly override it if the keyboard uses a microcontroller with
// more EEPROM *and* it makes sense to increase it.
#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047
# elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
# elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511
# else
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
# endif
#endif
// Due to usage of uint16_t check for max 65535
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 65535
# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536
@ -76,9 +61,37 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
#define VIAL_ENCODERS_SIZE 0
#endif
// Dynamic macro starts after encoders, or dynamic keymaps if encoders aren't enabled
#define VIAL_QMK_SETTINGS_EEPROM_ADDR (VIAL_ENCODERS_EEPROM_ADDR + VIAL_ENCODERS_SIZE)
// QMK settings area is just past encoders
#ifdef QMK_SETTINGS
#include "qmk_settings.h"
#define VIAL_QMK_SETTINGS_SIZE (sizeof(qmk_settings_t))
#else
#define VIAL_QMK_SETTINGS_SIZE 0
#endif
// Tap-dance
#define VIAL_TAP_DANCE_EEPROM_ADDR (VIAL_QMK_SETTINGS_EEPROM_ADDR + VIAL_QMK_SETTINGS_SIZE)
#ifdef VIAL_TAP_DANCE_ENABLE
#define VIAL_TAP_DANCE_SIZE (sizeof(vial_tap_dance_entry_t) * VIAL_TAP_DANCE_ENTRIES)
#else
#define VIAL_TAP_DANCE_SIZE 0
#endif
// Combos
#define VIAL_COMBO_EEPROM_ADDR (VIAL_TAP_DANCE_EEPROM_ADDR + VIAL_TAP_DANCE_SIZE)
#ifdef VIAL_COMBO_ENABLE
#define VIAL_COMBO_SIZE (sizeof(vial_combo_entry_t) * VIAL_COMBO_ENTRIES)
#else
#define VIAL_COMBO_SIZE 0
#endif
// Dynamic macro
#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_ENCODERS_EEPROM_ADDR + VIAL_ENCODERS_SIZE)
# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_COMBO_EEPROM_ADDR + VIAL_COMBO_SIZE)
#endif
// Sanity check that dynamic keymaps fit in available EEPROM
@ -86,7 +99,7 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
// The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it,
// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
// more than the default.
_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR >= 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
// Dynamic macros are stored after the keymaps and use what is available
// up to and including DYNAMIC_KEYMAP_EEPROM_MAX_ADDR.
@ -157,6 +170,68 @@ void dynamic_keymap_set_encoder(uint8_t layer, uint8_t idx, uint8_t dir, uint16_
}
#endif
#ifdef QMK_SETTINGS
uint8_t dynamic_keymap_get_qmk_settings(uint16_t offset) {
if (offset >= VIAL_QMK_SETTINGS_SIZE)
return 0;
void *address = (void*)(VIAL_QMK_SETTINGS_EEPROM_ADDR + offset);
return eeprom_read_byte(address);
}
void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value) {
if (offset >= VIAL_QMK_SETTINGS_SIZE)
return;
void *address = (void*)(VIAL_QMK_SETTINGS_EEPROM_ADDR + offset);
eeprom_update_byte(address, value);
}
#endif
#ifdef VIAL_TAP_DANCE_ENABLE
int dynamic_keymap_get_tap_dance(uint8_t index, vial_tap_dance_entry_t *entry) {
if (index >= VIAL_TAP_DANCE_ENTRIES)
return -1;
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
eeprom_read_block(entry, address, sizeof(vial_tap_dance_entry_t));
return 0;
}
int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *entry) {
if (index >= VIAL_TAP_DANCE_ENTRIES)
return -1;
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
eeprom_write_block(entry, address, sizeof(vial_tap_dance_entry_t));
return 0;
}
#endif
#ifdef VIAL_COMBO_ENABLE
int dynamic_keymap_get_combo(uint8_t index, vial_combo_entry_t *entry) {
if (index >= VIAL_COMBO_ENTRIES)
return -1;
void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t));
eeprom_read_block(entry, address, sizeof(vial_combo_entry_t));
return 0;
}
int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry) {
if (index >= VIAL_COMBO_ENTRIES)
return -1;
void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t));
eeprom_write_block(entry, address, sizeof(vial_combo_entry_t));
return 0;
}
#endif
#if defined(VIAL_ENCODERS_ENABLE) && defined(VIAL_ENCODER_DEFAULT)
static const uint16_t PROGMEM vial_encoder_default[] = VIAL_ENCODER_DEFAULT;
_Static_assert(sizeof(vial_encoder_default)/sizeof(*vial_encoder_default) == 2 * DYNAMIC_KEYMAP_LAYER_COUNT * NUMBER_OF_ENCODERS,
@ -193,6 +268,23 @@ void dynamic_keymap_reset(void) {
#endif
}
#ifdef QMK_SETTINGS
qmk_settings_reset();
#endif
#ifdef VIAL_TAP_DANCE_ENABLE
vial_tap_dance_entry_t td = { KC_NO, KC_NO, KC_NO, KC_NO, TAPPING_TERM };
for (size_t i = 0; i < VIAL_TAP_DANCE_ENTRIES; ++i) {
dynamic_keymap_set_tap_dance(i, &td);
}
#endif
#ifdef VIAL_COMBO_ENABLE
vial_combo_entry_t combo = { 0 };
for (size_t i = 0; i < VIAL_COMBO_ENTRIES; ++i)
dynamic_keymap_set_combo(i, &combo);
#endif
#ifdef VIAL_ENABLE
/* re-lock the keyboard */
vial_unlocked = vial_unlocked_prev;
@ -272,9 +364,7 @@ void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
}
}
#ifdef VIAL_ENCODERS_ENABLE
extern uint16_t g_vial_magic_keycode_override;
#endif
// This overrides the one in quantum/keymap_common.c
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) {
@ -282,10 +372,8 @@ uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) {
/* Disable any keycode processing while unlocking */
if (vial_unlock_in_progress)
return KC_NO;
#endif
#ifdef VIAL_ENCODERS_ENABLE
if (key.row == VIAL_ENCODER_MATRIX_MAGIC && key.col == VIAL_ENCODER_MATRIX_MAGIC)
if (key.row == VIAL_MATRIX_MAGIC && key.col == VIAL_MATRIX_MAGIC)
return g_vial_magic_keycode_override;
#endif

View File

@ -18,6 +18,10 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef VIAL_ENABLE
#include "vial.h"
#endif
#ifndef DYNAMIC_KEYMAP_LAYER_COUNT
# define DYNAMIC_KEYMAP_LAYER_COUNT 4
#endif
@ -30,6 +34,18 @@ void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column,
uint16_t dynamic_keymap_get_encoder(uint8_t layer, uint8_t idx, uint8_t dir);
void dynamic_keymap_set_encoder(uint8_t layer, uint8_t idx, uint8_t dir, uint16_t keycode);
#endif
#ifdef QMK_SETTINGS
uint8_t dynamic_keymap_get_qmk_settings(uint16_t offset);
void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value);
#endif
#ifdef VIAL_TAP_DANCE_ENABLE
int dynamic_keymap_get_tap_dance(uint8_t index, vial_tap_dance_entry_t *entry);
int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *entry);
#endif
#ifdef VIAL_COMBO_ENABLE
int dynamic_keymap_get_combo(uint8_t index, vial_combo_entry_t *entry);
int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry);
#endif
void dynamic_keymap_reset(void);
// These get/set the keycodes as stored in the EEPROM buffer
// Data is big-endian 16-bit values (the keycodes)

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#ifdef STM32_EEPROM_ENABLE
# include "eeprom_stm32.h"
#endif
// This is the default EEPROM max address to use for dynamic keymaps.
// The default is the ATmega32u4 EEPROM max address.
// Explicitly override it if the keyboard uses a microcontroller with
// more EEPROM *and* it makes sense to increase it.
#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047
# elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
# elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511
# elif defined(FEE_DENSITY_BYTES)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR FEE_DENSITY_BYTES-1
# else
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
# endif
#endif

View File

@ -22,6 +22,7 @@
#include "print.h"
#include "debug.h"
#include "mousekey.h"
#include "qmk_settings.h"
inline int8_t times_inv_sqrt2(int8_t x) {
// 181/256 is pretty close to 1/sqrt(2)
@ -74,17 +75,17 @@ uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
static uint8_t move_unit(void) {
uint16_t unit;
if (mousekey_accel & (1 << 0)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4;
unit = (QS_mousekey_move_delta * mk_max_speed) / 4;
} else if (mousekey_accel & (1 << 1)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
unit = (QS_mousekey_move_delta * mk_max_speed) / 2;
} else if (mousekey_accel & (1 << 2)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
unit = (QS_mousekey_move_delta * mk_max_speed);
} else if (mousekey_repeat == 0) {
unit = MOUSEKEY_MOVE_DELTA;
unit = QS_mousekey_move_delta;
} else if (mousekey_repeat >= mk_time_to_max) {
unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
unit = QS_mousekey_move_delta * mk_max_speed;
} else {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
unit = (QS_mousekey_move_delta * mk_max_speed * mousekey_repeat) / mk_time_to_max;
}
return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
}

View File

@ -165,6 +165,8 @@ extern uint8_t mk_delay;
extern uint8_t mk_interval;
extern uint8_t mk_max_speed;
extern uint8_t mk_time_to_max;
extern uint8_t mk_wheel_delay;
extern uint8_t mk_wheel_interval;
extern uint8_t mk_wheel_max_speed;
extern uint8_t mk_wheel_time_to_max;

View File

@ -20,6 +20,7 @@
# include <stdio.h>
# include "process_auto_shift.h"
# include "qmk_settings.h"
static uint16_t autoshift_time = 0;
static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
@ -45,16 +46,14 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
return true;
}
# ifndef AUTO_SHIFT_MODIFIERS
if (!QS_auto_shift_modifiers) {
if (get_mods()) {
return true;
}
# endif
# ifdef AUTO_SHIFT_REPEAT
}
if (QS_auto_shift_repeat) {
const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
if (!autoshift_flags.lastshifted) {
# endif
if (QS_auto_shift_no_auto_repeat || !autoshift_flags.lastshifted) {
if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) {
// Allow a tap-then-hold for keyrepeat.
if (!autoshift_flags.lastshifted) {
@ -66,10 +65,8 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
}
return false;
}
# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
}
# endif
# endif
}
// Record the keycode so we can simulate it later.
autoshift_lastkey = keycode;
@ -105,17 +102,15 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
add_weak_mods(MOD_BIT(KC_LSFT));
register_code(autoshift_lastkey);
autoshift_flags.lastshifted = true;
# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT)
if (QS_auto_shift_repeat && !QS_auto_shift_no_auto_repeat) {
if (matrix_trigger) {
// Prevents release.
return;
}
# endif
}
}
# if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
# endif
qs_wait_ms(QS_tap_code_delay);
unregister_code(autoshift_lastkey);
del_weak_mods(MOD_BIT(KC_LSFT));
} else {
@ -140,6 +135,8 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
* to be released.
*/
void autoshift_matrix_scan(void) {
if (!QS_auto_shift_enable) return;
if (autoshift_flags.in_progress) {
const uint16_t now = timer_read();
const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
@ -178,6 +175,7 @@ uint16_t get_autoshift_timeout(void) { return autoshift_timeout; }
void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; }
bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
if (!QS_auto_shift_enable) return true;
// Note that record->event.time isn't reliable, see:
// https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550
const uint16_t now = timer_read();
@ -229,18 +227,16 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
# ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z:
# endif
# ifndef NO_AUTO_SHIFT_NUMERIC
if (!QS_auto_shift_no_auto_shift_alpha) return true;
case KC_1 ... KC_0:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
if (!QS_auto_shift_no_auto_shift_numeric) return true;
break;
case KC_TAB:
case KC_MINUS ... KC_SLASH:
case KC_NONUS_BSLASH:
# endif
return true;
if (!QS_auto_shift_no_auto_shift_special) return true;
break;
}
return false;
}

View File

@ -16,6 +16,11 @@
#include "print.h"
#include "process_combo.h"
#include "qmk_settings.h"
#ifdef VIAL_COMBO_ENABLE
#include "dynamic_keymap.h"
#endif
#ifndef COMBO_VARIABLE_LEN
__attribute__((weak)) combo_t key_combos[COMBO_COUNT] = {};
@ -29,7 +34,6 @@ __attribute__((weak)) void process_combo_event(uint16_t combo_index, bool presse
static uint16_t timer = 0;
static uint16_t current_combo_index = 0;
static bool drop_buffer = false;
static bool is_active = false;
static bool b_combo_enable = true; // defaults to enabled
static uint8_t buffer_size = 0;
@ -71,7 +75,19 @@ static inline void dump_key_buffer(bool emit) {
buffer_size = 0;
}
#define ALL_COMBO_KEYS_ARE_DOWN (((1 << count) - 1) == combo->state)
static void end_incomplete_combos(void) {
#ifndef COMBO_VARIABLE_LEN
for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) {
#else
for (current_combo_index = 0; current_combo_index < COMBO_LEN; ++current_combo_index) {
#endif
combo_t *combo = &key_combos[current_combo_index];
if (!(combo->state & COMBO_COMPLETE))
combo->state = 0;
}
}
#define ALL_COMBO_KEYS_ARE_DOWN (((1 << count) - 1) == (combo->state & ~COMBO_COMPLETE))
#define KEY_STATE_DOWN(key) \
do { \
combo->state |= (1 << key); \
@ -80,27 +96,45 @@ static inline void dump_key_buffer(bool emit) {
do { \
combo->state &= ~(1 << key); \
} while (0)
#define KEY_STATE(key) (combo->state & (1 << (key)))
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) {
uint8_t count = 0;
uint16_t index = -1;
#ifdef VIAL_COMBO_ENABLE
uint8_t combo_idx = (uintptr_t)combo->keys;
vial_combo_entry_t entry;
if (dynamic_keymap_get_combo(combo_idx, &entry) != 0)
return false;
for (count = 0; count < sizeof(entry.input)/sizeof(*entry.input); ++count) {
uint16_t key = entry.input[count];
if (key == KC_NO) break;
if (key == keycode) index = count;
}
/* must have at least 2 keys in the combo */
if (count < 2)
return false;
#else
/* Find index of keycode and number of combo keys */
for (const uint16_t *keys = combo->keys;; ++count) {
uint16_t key = pgm_read_word(&keys[count]);
if (keycode == key) index = count;
if (COMBO_END == key) break;
}
#endif
/* Continue processing if not a combo key */
if (-1 == (int8_t)index) return false;
bool is_combo_active = is_active;
bool is_combo_active = true;
if (record->event.pressed) {
KEY_STATE_DOWN(index);
if (is_combo_active) {
if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
dump_key_buffer(false);
combo->state |= COMBO_COMPLETE;
send_combo(combo->keycode, true);
drop_buffer = true;
}
@ -108,22 +142,31 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
} else {
if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */
send_combo(combo->keycode, false);
} else {
/* continue processing without immediately returning */
is_combo_active = false;
}
KEY_STATE_UP(index);
/* don't consume the key unless it is a part of a completed combo */
is_combo_active = false;
if (KEY_STATE(index)) {
KEY_STATE_UP(index);
if (combo->state & COMBO_COMPLETE) {
/* Consume the key on release, only if the combo was complete */
is_combo_active = true;
/* if all keys are up, reset the combo */
if (combo->state == COMBO_COMPLETE)
combo->state = 0;
}
}
}
return is_combo_active;
}
#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state)
#define NO_COMBO_KEYS_ARE_DOWN (0 == (combo->state & ~COMBO_COMPLETE))
bool process_combo(uint16_t keycode, keyrecord_t *record) {
bool is_combo_key = false;
drop_buffer = false;
bool no_combo_keys_pressed = true;
if (keycode == CMB_ON && record->event.pressed) {
@ -158,17 +201,12 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
/* buffer is only dropped when we complete a combo, so we refresh the timer
* here */
timer = timer_read();
dump_key_buffer(false);
drop_buffer = false;
} else if (!is_combo_key) {
/* if no combos claim the key we need to emit the keybuffer */
dump_key_buffer(true);
// reset state if there are no combo keys pressed at all
if (no_combo_keys_pressed) {
timer = 0;
is_active = true;
}
} else if (record->event.pressed && is_active) {
end_incomplete_combos();
} else if (record->event.pressed) {
/* otherwise the key is consumed and placed in the buffer */
timer = timer_read();
@ -185,19 +223,19 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
}
void matrix_scan_combo(void) {
if (b_combo_enable && is_active && timer && timer_elapsed(timer) > COMBO_TERM) {
if (b_combo_enable && timer && timer_elapsed(timer) > QS_combo_term) {
/* This disables the combo, meaning key events for this
* combo will be handled by the next processors in the chain
*/
is_active = false;
dump_key_buffer(true);
end_incomplete_combos();
}
}
void combo_enable(void) { b_combo_enable = true; }
void combo_disable(void) {
b_combo_enable = is_active = false;
b_combo_enable = false;
timer = 0;
dump_key_buffer(true);
}

View File

@ -16,16 +16,23 @@
#pragma once
#ifdef VIAL_ENABLE
#include "vial.h"
#endif
#include "progmem.h"
#include "quantum.h"
#include <stdint.h>
#ifdef EXTRA_EXTRA_LONG_COMBOS
# define MAX_COMBO_LENGTH 32
# define MAX_COMBO_LENGTH 31
# define COMBO_COMPLETE 0x80000000u
#elif EXTRA_LONG_COMBOS
# define MAX_COMBO_LENGTH 16
# define MAX_COMBO_LENGTH 15
# define COMBO_COMPLETE 0x8000u
#else
# define MAX_COMBO_LENGTH 8
# define MAX_COMBO_LENGTH 7
# define COMBO_COMPLETE 0x80u
#endif
typedef struct {

View File

@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "process_grave_esc.h"
#include "qmk_settings.h"
/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
* Used to ensure that the correct keycode is released if the key is released.
@ -25,35 +26,35 @@ bool process_grave_esc(uint16_t keycode, keyrecord_t *record) {
const uint8_t mods = get_mods();
uint8_t shifted = mods & MOD_MASK_SG;
#ifdef GRAVE_ESC_ALT_OVERRIDE
if (QS_grave_esc_alt_override) {
// if ALT is pressed, ESC is always sent
// this is handy for the cmd+opt+esc shortcut on macOS, among other things.
if (mods & MOD_MASK_ALT) {
shifted = 0;
}
#endif
}
#ifdef GRAVE_ESC_CTRL_OVERRIDE
if (QS_grave_esc_ctrl_override) {
// if CTRL is pressed, ESC is always sent
// this is handy for the ctrl+shift+esc shortcut on windows, among other things.
if (mods & MOD_MASK_CTRL) {
shifted = 0;
}
#endif
}
#ifdef GRAVE_ESC_GUI_OVERRIDE
if (QS_grave_esc_gui_override) {
// if GUI is pressed, ESC is always sent
if (mods & MOD_MASK_GUI) {
shifted = 0;
}
#endif
}
#ifdef GRAVE_ESC_SHIFT_OVERRIDE
if (QS_grave_esc_shift_override) {
// if SHIFT is pressed, ESC is always sent
if (mods & MOD_MASK_SHIFT) {
shifted = 0;
}
#endif
}
if (record->event.pressed) {
grave_esc_was_shifted = shifted;

177
quantum/qmk_settings.c Normal file
View File

@ -0,0 +1,177 @@
#include "qmk_settings.h"
#include <stddef.h>
#include <string.h>
#include "progmem.h"
#include "dynamic_keymap.h"
#include "process_auto_shift.h"
#include "mousekey.h"
#include "process_combo.h"
#include "action_tapping.h"
qmk_settings_t QS;
#define DECLARE_SETTING(id, field) { .qsid=id, .ptr=&QS.field, .sz=sizeof(QS.field) }
#define DECLARE_SETTING_CB(id, field, callback) { .qsid=id, .ptr=&QS.field, .sz=sizeof(QS.field), .cb=callback }
static void auto_shift_timeout_apply(void) {
set_autoshift_timeout(QS.auto_shift_timeout);
}
static void mousekey_apply(void) {
mk_delay = QS.mousekey_delay / 10;
mk_interval = QS.mousekey_interval;
mk_max_speed = QS.mousekey_max_speed;
mk_time_to_max = QS.mousekey_time_to_max;
mk_wheel_delay = QS.mousekey_wheel_delay / 10;
mk_wheel_interval = QS.mousekey_wheel_interval;
mk_wheel_max_speed = QS.mousekey_wheel_max_speed;
mk_wheel_time_to_max = QS.mousekey_wheel_time_to_max;
}
static const qmk_settings_proto_t protos[] PROGMEM = {
DECLARE_SETTING(1, grave_esc_override),
DECLARE_SETTING(2, combo_term),
DECLARE_SETTING(3, auto_shift),
DECLARE_SETTING_CB(4, auto_shift_timeout, auto_shift_timeout_apply),
DECLARE_SETTING(5, osk_tap_toggle),
DECLARE_SETTING(6, osk_timeout),
DECLARE_SETTING(7, tapping_term),
DECLARE_SETTING(8, tapping),
DECLARE_SETTING_CB(9, mousekey_delay, mousekey_apply),
DECLARE_SETTING_CB(10, mousekey_interval, mousekey_apply),
DECLARE_SETTING_CB(11, mousekey_move_delta, mousekey_apply),
DECLARE_SETTING_CB(12, mousekey_max_speed, mousekey_apply),
DECLARE_SETTING_CB(13, mousekey_time_to_max, mousekey_apply),
DECLARE_SETTING_CB(14, mousekey_wheel_delay, mousekey_apply),
DECLARE_SETTING_CB(15, mousekey_wheel_interval, mousekey_apply),
DECLARE_SETTING_CB(16, mousekey_wheel_max_speed, mousekey_apply),
DECLARE_SETTING_CB(17, mousekey_wheel_time_to_max, mousekey_apply),
DECLARE_SETTING(18, tap_code_delay),
DECLARE_SETTING(19, tap_hold_caps_delay),
};
static const qmk_settings_proto_t *find_setting(uint16_t qsid) {
for (size_t i = 0; i < sizeof(protos)/sizeof(*protos); ++i)
if (pgm_read_word(&protos[i].qsid) == qsid)
return &protos[i];
return NULL;
}
static void load_settings(void) {
for (size_t i = 0; i < sizeof(qmk_settings_t); ++i) {
uint8_t byte;
byte = dynamic_keymap_get_qmk_settings(i);
memcpy((char*)&QS + i, &byte, 1);
}
}
static void save_settings(void) {
for (size_t i = 0; i < sizeof(qmk_settings_t); ++i) {
uint8_t old_byte, new_byte;
old_byte = dynamic_keymap_get_qmk_settings(i);
memcpy(&new_byte, (char*)&QS + i, 1);
if (old_byte != new_byte)
dynamic_keymap_set_qmk_settings(i, new_byte);
}
}
void qmk_settings_init(void) {
load_settings();
/* execute all callbacks to initialize the settings */
for (size_t i = 0; i < sizeof(protos)/sizeof(*protos); ++i) {
const qmk_settings_proto_t *proto = &protos[i];
qmk_setting_callback_t cb = pgm_read_ptr(&proto->cb);
if (cb)
cb();
}
}
void qmk_settings_reset(void) {
QS.grave_esc_override = 0;
QS.auto_shift = 0;
QS.auto_shift_timeout = AUTO_SHIFT_TIMEOUT;
QS.osk_tap_toggle = ONESHOT_TAP_TOGGLE;
QS.osk_timeout = ONESHOT_TIMEOUT;
QS.mousekey_delay = MOUSEKEY_DELAY;
QS.mousekey_interval = MOUSEKEY_INTERVAL;
QS.mousekey_move_delta = MOUSEKEY_MOVE_DELTA;
QS.mousekey_max_speed = MOUSEKEY_MAX_SPEED;
QS.mousekey_time_to_max = MOUSEKEY_TIME_TO_MAX;
QS.mousekey_wheel_delay = MOUSEKEY_WHEEL_DELAY;
QS.mousekey_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
QS.mousekey_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
QS.mousekey_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
QS.combo_term = COMBO_TERM;
QS.tapping_term = TAPPING_TERM;
QS.tapping = 0;
QS.tap_code_delay = TAP_CODE_DELAY;
QS.tap_hold_caps_delay = TAP_HOLD_CAPS_DELAY;
save_settings();
/* to trigger all callbacks */
qmk_settings_init();
}
void qmk_settings_query(uint16_t qsid_gt, void *buffer, size_t sz) {
/* set all FFs, so caller can identify when all settings are retrieved by looking for an 0xFFFF entry */
memset(buffer, 0xFF, sz);
size_t buffer_offset = 0;
for (size_t i = 0; i < sizeof(protos)/sizeof(*protos); ++i) {
uint16_t qsid;
/* if output buffer has no space left, bail out */
if (buffer_offset + sizeof(qsid) > sz)
break;
qsid = pgm_read_word(&protos[i].qsid);
if (qsid > qsid_gt) {
memcpy((char*)buffer + buffer_offset, &qsid, sizeof(qsid));
buffer_offset += sizeof(qsid);
}
}
}
int qmk_settings_get(uint16_t qsid, void *setting, size_t maxsz) {
const qmk_settings_proto_t *proto = find_setting(qsid);
if (!proto || pgm_read_word(&proto->sz) > maxsz)
return -1;
memcpy(setting, pgm_read_ptr(&proto->ptr), pgm_read_word(&proto->sz));
return 0;
}
int qmk_settings_set(uint16_t qsid, const void *setting, size_t maxsz) {
const qmk_settings_proto_t *proto = find_setting(qsid);
if (!proto || pgm_read_word(&proto->sz) > maxsz)
return -1;
memcpy(pgm_read_ptr(&proto->ptr), setting, pgm_read_word(&proto->sz));
save_settings();
qmk_setting_callback_t cb = pgm_read_ptr(&proto->cb);
if (cb)
cb();
return 0;
}
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
return QS.tapping_term;
}
bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) {
return QS.tapping & 1;
}
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
return QS.tapping & 2;
}
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) {
return QS.tapping & 4;
}
bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
return QS.tapping & 8;
}

214
quantum/qmk_settings.h Normal file
View File

@ -0,0 +1,214 @@
#pragma once
#include <inttypes.h>
#include <stddef.h>
/* take qmk config macros and set up helper variables for default settings */
#ifndef TAP_CODE_DELAY
# define TAP_CODE_DELAY 10
#endif
#ifndef TAP_HOLD_CAPS_DELAY
# define TAP_HOLD_CAPS_DELAY 80
#endif
/* ========================================================================== */
/* Grave escape */
/* ========================================================================== */
#ifdef GRAVE_ESC_ALT_OVERRIDE
#define GRAVE_ESC_ALT_OVERRIDE_Defined 1
#else
#define GRAVE_ESC_ALT_OVERRIDE_Defined 0
#endif
#ifdef GRAVE_ESC_CTRL_OVERRIDE
#define GRAVE_ESC_CTRL_OVERRIDE_Defined 1
#else
#define GRAVE_ESC_CTRL_OVERRIDE_Defined 0
#endif
#ifdef GRAVE_ESC_GUI_OVERRIDE
#define GRAVE_ESC_GUI_OVERRIDE_Defined 1
#else
#define GRAVE_ESC_GUI_OVERRIDE_Defined 0
#endif
#ifdef GRAVE_ESC_SHIFT_OVERRIDE
#define GRAVE_ESC_SHIFT_OVERRIDE_Defined 1
#else
#define GRAVE_ESC_SHIFT_OVERRIDE_Defined 0
#endif
/* ========================================================================== */
/* Auto shift */
/* ========================================================================== */
#ifdef AUTO_SHIFT_ENABLE
#define AUTO_SHIFT_ENABLE_Defined 1
#else
#define AUTO_SHIFT_ENABLE_Defined 0
#endif
#ifdef AUTO_SHIFT_MODIFIERS
#define AUTO_SHIFT_MODIFIERS_Defined 1
#else
#define AUTO_SHIFT_MODIFIERS_Defined 0
#endif
#ifdef NO_AUTO_SHIFT_SPECIAL
#define NO_AUTO_SHIFT_SPECIAL_Defined 1
#else
#define NO_AUTO_SHIFT_SPECIAL_Defined 0
#endif
#ifdef NO_AUTO_SHIFT_NUMERIC
#define NO_AUTO_SHIFT_NUMERIC_Defined 1
#else
#define NO_AUTO_SHIFT_NUMERIC_Defined 0
#endif
#ifdef NO_AUTO_SHIFT_ALPHA
#define NO_AUTO_SHIFT_ALPHA_Defined 1
#else
#define NO_AUTO_SHIFT_ALPHA_Defined 0
#endif
#ifdef AUTO_SHIFT_REPEAT
#define AUTO_SHIFT_REPEAT_Defined 1
#else
#define AUTO_SHIFT_REPEAT_Defined 0
#endif
#ifdef AUTO_SHIFT_NO_AUTO_REPEAT
#define AUTO_SHIFT_NO_AUTO_REPEAT_Defined 1
#else
#define AUTO_SHIFT_NO_AUTO_REPEAT_Defined 0
#endif
/* ========================================================================== */
/* One shot keys */
/* ========================================================================== */
#ifndef ONESHOT_TAP_TOGGLE
#define ONESHOT_TAP_TOGGLE 5
#endif
#ifndef ONESHOT_TIMEOUT
#define ONESHOT_TIMEOUT 5000
#endif
#ifdef QMK_SETTINGS
/* dynamic settings framework is enabled */
/* actual settings - stored in RAM and backed by EEPROM
these are in arbitrary order to ensure they are aligned w/o any holes, and the order can be changed at will */
typedef struct {
uint16_t auto_shift_timeout;
uint16_t osk_timeout;
uint16_t mousekey_delay;
uint16_t mousekey_interval;
uint16_t mousekey_move_delta;
uint16_t mousekey_max_speed;
uint16_t mousekey_time_to_max;
uint16_t mousekey_wheel_delay;
uint16_t mousekey_wheel_interval;
uint16_t mousekey_wheel_max_speed;
uint16_t mousekey_wheel_time_to_max;
uint16_t combo_term;
uint16_t tapping_term;
uint8_t grave_esc_override;
uint8_t auto_shift;
uint8_t osk_tap_toggle;
uint8_t tapping;
uint16_t tap_code_delay;
uint16_t tap_hold_caps_delay;
} qmk_settings_t;
_Static_assert(sizeof(qmk_settings_t) == 34, "unexpected size of the qmk_settings_t structure");
typedef void (*qmk_setting_callback_t)(void);
/* setting prototype - describes how to get/set settings, stored in flash */
typedef struct {
uint16_t qsid;
uint16_t sz;
void *ptr;
qmk_setting_callback_t cb;
} qmk_settings_proto_t;
void qmk_settings_init(void);
void qmk_settings_reset(void);
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);
extern qmk_settings_t QS;
/* Grave escape */
#define QS_grave_esc_alt_override (QS.grave_esc_override & 1)
#define QS_grave_esc_ctrl_override (QS.grave_esc_override & 2)
#define QS_grave_esc_gui_override (QS.grave_esc_override & 4)
#define QS_grave_esc_shift_override (QS.grave_esc_override & 8)
/* Auto shift */
#define QS_auto_shift_enable (QS.auto_shift & 1)
#define QS_auto_shift_modifiers (QS.auto_shift & 2)
#define QS_auto_shift_no_auto_shift_special (QS.auto_shift & 4)
#define QS_auto_shift_no_auto_shift_numeric (QS.auto_shift & 8)
#define QS_auto_shift_no_auto_shift_alpha (QS.auto_shift & 16)
#define QS_auto_shift_repeat (QS.auto_shift & 32)
#define QS_auto_shift_no_auto_repeat (QS.auto_shift & 64)
/* One Shot Keys */
#define QS_oneshot_tap_toggle (QS.osk_tap_toggle)
#define QS_oneshot_timeout (QS.osk_timeout)
/* Mouse keys */
#define QS_mousekey_move_delta (QS.mousekey_move_delta)
/* Combo */
#define QS_combo_term (QS.combo_term)
/* Tap delays */
#define QS_tap_code_delay (QS.tap_code_delay)
#define QS_tap_hold_caps_delay (QS.tap_hold_caps_delay)
#else
/* dynamic settings framework is disabled => hardcode the settings and let the compiler optimize extra branches out */
/* Grave escape */
#define QS_grave_esc_alt_override GRAVE_ESC_ALT_OVERRIDE_Defined
#define QS_grave_esc_ctrl_override GRAVE_ESC_CTRL_OVERRIDE_Defined
#define QS_grave_esc_gui_override GRAVE_ESC_GUI_OVERRIDE_Defined
#define QS_grave_esc_shift_override GRAVE_ESC_SHIFT_OVERRIDE_Defined
/* Auto shift */
#define QS_auto_shift_enable AUTO_SHIFT_ENABLE_Defined
#define QS_auto_shift_modifiers AUTO_SHIFT_MODIFIERS_Defined
#define QS_auto_shift_no_auto_shift_special NO_AUTO_SHIFT_SPECIAL_Defined
#define QS_auto_shift_no_auto_shift_numeric NO_AUTO_SHIFT_NUMERIC_Defined
#define QS_auto_shift_no_auto_shift_alpha NO_AUTO_SHIFT_ALPHA_Defined
#define QS_auto_shift_repeat AUTO_SHIFT_REPEAT_Defined
#define QS_auto_shift_no_auto_repeat AUTO_SHIFT_NO_AUTO_REPEAT_Defined
/* One Shot Keys */
#define QS_oneshot_tap_toggle ONESHOT_TAP_TOGGLE
#define QS_oneshot_timeout ONESHOT_TIMEOUT
/* Mouse keys */
#define QS_mousekey_move_delta MOUSEKEY_MOVE_DELTA
/* Combo */
#define QS_combo_term COMBO_TERM
/* Tap delays */
#define QS_tap_code_delay TAP_CODE_DELAY
#define QS_tap_hold_caps_delay TAP_HOLD_CAPS_DELAY
#endif
#if defined(__AVR__) && defined(QMK_SETTINGS)
#include <util/delay.h>
static inline void qs_wait_ms(uint16_t timer) {
while (timer--) _delay_ms(1);
}
#else
#define qs_wait_ms wait_ms
#endif

View File

@ -16,6 +16,7 @@
#include "quantum.h"
#include "magic.h"
#include "qmk_settings.h"
#ifdef BLUETOOTH_ENABLE
# include "outputselect.h"
@ -107,9 +108,7 @@ void unregister_code16(uint16_t code) {
void tap_code16(uint16_t code) {
register_code16(code);
#if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
#endif
qs_wait_ms(QS_tap_code_delay);
unregister_code16(code);
}

View File

@ -71,11 +71,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv
# undef RGB_DISABLE_WHEN_USB_SUSPENDED
#endif
#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
#endif
#if !defined(RGB_MATRIX_HUE_STEP)
# define RGB_MATRIX_HUE_STEP 8
#endif

View File

@ -224,3 +224,8 @@ extern last_hit_t g_last_hit_tracker;
#ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS
extern uint8_t g_rgb_frame_buffer[MATRIX_ROWS][MATRIX_COLS];
#endif
#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
#endif

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
#define RGB_MATRIX_EFFECT_ALPHAS_MODS
RGB_MATRIX_EFFECT(ALPHAS_MODS)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BREATHING
#define RGB_MATRIX_EFFECT_BREATHING
RGB_MATRIX_EFFECT(BREATHING)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
#define RGB_MATRIX_EFFECT_BAND_PINWHEEL_SAT
RGB_MATRIX_EFFECT(BAND_PINWHEEL_SAT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
#define RGB_MATRIX_EFFECT_BAND_PINWHEEL_VAL
RGB_MATRIX_EFFECT(BAND_PINWHEEL_VAL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_SAT
#define RGB_MATRIX_EFFECT_BAND_SAT
RGB_MATRIX_EFFECT(BAND_SAT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
#define RGB_MATRIX_EFFECT_BAND_SPIRAL_SAT
RGB_MATRIX_EFFECT(BAND_SPIRAL_SAT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL
#define RGB_MATRIX_EFFECT_BAND_SPIRAL_VAL
RGB_MATRIX_EFFECT(BAND_SPIRAL_VAL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_BAND_VAL
#define RGB_MATRIX_EFFECT_BAND_VAL
RGB_MATRIX_EFFECT(BAND_VAL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
#define RGB_MATRIX_EFFECT_CYCLE_ALL
RGB_MATRIX_EFFECT(CYCLE_ALL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
#define RGB_MATRIX_EFFECT_CYCLE_LEFT_RIGHT
RGB_MATRIX_EFFECT(CYCLE_LEFT_RIGHT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN
#define RGB_MATRIX_EFFECT_CYCLE_OUT_IN
RGB_MATRIX_EFFECT(CYCLE_OUT_IN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
#define RGB_MATRIX_EFFECT_CYCLE_OUT_IN_DUAL
RGB_MATRIX_EFFECT(CYCLE_OUT_IN_DUAL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_PINWHEEL
#define RGB_MATRIX_EFFECT_CYCLE_PINWHEEL
RGB_MATRIX_EFFECT(CYCLE_PINWHEEL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_SPIRAL
#define RGB_MATRIX_EFFECT_CYCLE_SPIRAL
RGB_MATRIX_EFFECT(CYCLE_SPIRAL)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
#define RGB_MATRIX_EFFECT_CYCLE_UP_DOWN
RGB_MATRIX_EFFECT(CYCLE_UP_DOWN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
#define RGB_MATRIX_EFFECT_DIGITAL_RAIN
RGB_MATRIX_EFFECT(DIGITAL_RAIN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
#define RGB_MATRIX_EFFECT_DUAL_BEACON
RGB_MATRIX_EFFECT(DUAL_BEACON)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
#define RGB_MATRIX_EFFECT_GRADIENT_LEFT_RIGHT
RGB_MATRIX_EFFECT(GRADIENT_LEFT_RIGHT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
#define RGB_MATRIX_EFFECT_GRADIENT_UP_DOWN
RGB_MATRIX_EFFECT(GRADIENT_UP_DOWN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_HUE_BREATHING
#define RGB_MATRIX_EFFECT_HUE_BREATHING
RGB_MATRIX_EFFECT(HUE_BREATHING)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_HUE_PENDULUM
#define RGB_MATRIX_EFFECT_HUE_PENDULUM
RGB_MATRIX_EFFECT(HUE_PENDULUM)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_HUE_WAVE
#define RGB_MATRIX_EFFECT_HUE_WAVE
RGB_MATRIX_EFFECT(HUE_WAVE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
#define RGB_MATRIX_EFFECT_JELLYBEAN_RAINDROPS
RGB_MATRIX_EFFECT(JELLYBEAN_RAINDROPS)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
#define RGB_MATRIX_EFFECT_RAINBOW_BEACON
RGB_MATRIX_EFFECT(RAINBOW_BEACON)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
#define RGB_MATRIX_EFFECT_RAINBOW_MOVING_CHEVRON
RGB_MATRIX_EFFECT(RAINBOW_MOVING_CHEVRON)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
#define RGB_MATRIX_EFFECT_RAINBOW_PINWHEELS
RGB_MATRIX_EFFECT(RAINBOW_PINWHEELS)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,4 +1,5 @@
#ifndef DISABLE_RGB_MATRIX_RAINDROPS
#define RGB_MATRIX_EFFECT_RAINDROPS
RGB_MATRIX_EFFECT(RAINDROPS)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -35,3 +35,4 @@
#include "rgb_matrix_animations/solid_reactive_nexus.h"
#include "rgb_matrix_animations/splash_anim.h"
#include "rgb_matrix_animations/solid_splash_anim.h"
#include "rgb_matrix_animations/vialrgb_direct_anim.h"

View File

@ -1,3 +1,4 @@
#define RGB_MATRIX_EFFECT_SOLID_COLOR
RGB_MATRIX_EFFECT(SOLID_COLOR)
#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -1,5 +1,6 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE
RGB_MATRIX_EFFECT(SOLID_REACTIVE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -2,10 +2,12 @@
# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_CROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
# endif
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTICROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS)
# endif

View File

@ -2,10 +2,12 @@
# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_NEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS)
# endif
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTINEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS)
# endif

View File

@ -1,5 +1,6 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_SIMPLE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -2,10 +2,12 @@
# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_WIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
# endif
# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
#define RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTIWIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE)
# endif

View File

@ -2,10 +2,12 @@
# if !defined(DISABLE_RGB_MATRIX_SOLID_SPLASH) || !defined(DISABLE_RGB_MATRIX_SOLID_MULTISPLASH)
# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
#define RGB_MATRIX_EFFECT_SOLID_SPLASH
RGB_MATRIX_EFFECT(SOLID_SPLASH)
# endif
# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
#define RGB_MATRIX_EFFECT_SOLID_MULTISPLASH
RGB_MATRIX_EFFECT(SOLID_MULTISPLASH)
# endif

View File

@ -2,10 +2,12 @@
# if !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
# ifndef DISABLE_RGB_MATRIX_SPLASH
#define RGB_MATRIX_EFFECT_SPLASH
RGB_MATRIX_EFFECT(SPLASH)
# endif
# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
#define RGB_MATRIX_EFFECT_MULTISPLASH
RGB_MATRIX_EFFECT(MULTISPLASH)
# endif

View File

@ -1,4 +1,5 @@
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP)
#define RGB_MATRIX_EFFECT_TYPING_HEATMAP
RGB_MATRIX_EFFECT(TYPING_HEATMAP)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS

View File

@ -0,0 +1,18 @@
#if defined(VIALRGB_ENABLE) && !defined(VIALRGB_NO_DIRECT)
#define RGB_MATRIX_EFFECT_VIALRGB_DIRECT
RGB_MATRIX_EFFECT(VIALRGB_DIRECT)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
extern HSV g_direct_mode_colors[DRIVER_LED_TOTAL];
bool VIALRGB_DIRECT(effect_params_t* params) {
RGB_MATRIX_USE_LIMITS(led_min, led_max);
for (uint8_t i = led_min; i < led_max; i++) {
RGB rgb = rgb_matrix_hsv_to_rgb(g_direct_mode_colors[i]);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
return led_max < DRIVER_LED_TOTAL;
}
# endif
#endif

View File

@ -52,6 +52,10 @@
#include "vial.h"
#endif
#ifdef VIALRGB_ENABLE
#include "vialrgb.h"
#endif
// Forward declare some helpers.
#if defined(VIA_QMK_BACKLIGHT_ENABLE)
void via_qmk_backlight_set_value(uint8_t *data);
@ -322,10 +326,13 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
#if defined(VIA_QMK_RGBLIGHT_ENABLE)
via_qmk_rgblight_set_value(command_data);
#endif
#if defined(VIALRGB_ENABLE)
vialrgb_set_value(data, length);
#endif
#if defined(VIA_CUSTOM_LIGHTING_ENABLE)
raw_hid_receive_kb(data, length);
#endif
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIALRGB_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
// Return the unhandled state
*command_id = id_unhandled;
#endif
@ -338,10 +345,13 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
#if defined(VIA_QMK_RGBLIGHT_ENABLE)
via_qmk_rgblight_get_value(command_data);
#endif
#if defined(VIALRGB_ENABLE)
vialrgb_get_value(data, length);
#endif
#if defined(VIA_CUSTOM_LIGHTING_ENABLE)
raw_hid_receive_kb(data, length);
#endif
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIALRGB_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
// Return the unhandled state
*command_id = id_unhandled;
#endif
@ -354,10 +364,13 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
#if defined(VIA_QMK_RGBLIGHT_ENABLE)
eeconfig_update_rgblight_current();
#endif
#if defined(VIALRGB_ENABLE)
vialrgb_save(data, length);
#endif
#if defined(VIA_CUSTOM_LIGHTING_ENABLE)
raw_hid_receive_kb(data, length);
#endif
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
#if !defined(VIA_QMK_BACKLIGHT_ENABLE) && !defined(VIA_QMK_RGBLIGHT_ENABLE) && !defined(VIALRGB_ENABLE) && !defined(VIA_CUSTOM_LIGHTING_ENABLE)
// Return the unhandled state
*command_id = id_unhandled;
#endif

View File

@ -44,12 +44,29 @@ _Static_assert(VIAL_UNLOCK_NUM_KEYS < 15, "Max 15 unlock keys");
_Static_assert(sizeof(vial_unlock_combo_rows) == sizeof(vial_unlock_combo_cols), "The number of unlock cols and rows should be the same");
#endif
#define VIAL_RAW_EPSIZE 32
#ifndef VIAL_ENCODER_KEYCODE_DELAY
#define VIAL_ENCODER_KEYCODE_DELAY 10
#endif
#include "qmk_settings.h"
#ifdef VIAL_TAP_DANCE_ENABLE
static void reload_tap_dance(void);
#endif
#ifdef VIAL_COMBO_ENABLE
static void init_combo(void);
#endif
void vial_init(void) {
#ifdef VIAL_TAP_DANCE_ENABLE
reload_tap_dance();
#endif
#ifdef VIAL_COMBO_ENABLE
init_combo();
#endif
}
void vial_handle_cmd(uint8_t *msg, uint8_t length) {
/* All packets must be fixed 32 bytes */
if (length != VIAL_RAW_EPSIZE)
@ -61,11 +78,15 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) {
case vial_get_keyboard_id: {
uint8_t keyboard_uid[] = VIAL_KEYBOARD_UID;
memset(msg, 0, length);
msg[0] = VIAL_PROTOCOL_VERSION & 0xFF;
msg[1] = (VIAL_PROTOCOL_VERSION >> 8) & 0xFF;
msg[2] = (VIAL_PROTOCOL_VERSION >> 16) & 0xFF;
msg[3] = (VIAL_PROTOCOL_VERSION >> 24) & 0xFF;
memcpy(&msg[4], keyboard_uid, 8);
#ifdef VIALRGB_ENABLE
msg[12] = 1; /* bit flag to indicate vialrgb is supported - so third-party apps don't have to query json */
#endif
break;
}
/* Retrieve keyboard definition size */
@ -160,40 +181,124 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) {
#endif
break;
}
case vial_qmk_settings_query: {
#ifdef QMK_SETTINGS
uint16_t qsid_greater_than = msg[2] | (msg[3] << 8);
qmk_settings_query(qsid_greater_than, msg, length);
#else
memset(msg, 0xFF, length); /* indicate that we don't support any qsid */
#endif
break;
}
#ifdef QMK_SETTINGS
case vial_qmk_settings_get: {
uint16_t qsid = msg[2] | (msg[3] << 8);
msg[0] = qmk_settings_get(qsid, &msg[1], length - 1);
break;
}
case vial_qmk_settings_set: {
uint16_t qsid = msg[2] | (msg[3] << 8);
msg[0] = qmk_settings_set(qsid, &msg[4], length - 4);
break;
}
case vial_qmk_settings_reset: {
qmk_settings_reset();
break;
}
#endif
case vial_dynamic_entry_op: {
switch (msg[2]) {
case dynamic_vial_get_number_of_entries: {
memset(msg, 0, length);
msg[0] = VIAL_TAP_DANCE_ENTRIES;
msg[1] = VIAL_COMBO_ENTRIES;
break;
}
#ifdef VIAL_TAP_DANCE_ENABLE
case dynamic_vial_tap_dance_get: {
uint8_t idx = msg[3];
vial_tap_dance_entry_t td = { 0 };
msg[0] = dynamic_keymap_get_tap_dance(idx, &td);
memcpy(&msg[1], &td, sizeof(td));
break;
}
case dynamic_vial_tap_dance_set: {
uint8_t idx = msg[3];
vial_tap_dance_entry_t td;
memcpy(&td, &msg[4], sizeof(td));
msg[0] = dynamic_keymap_set_tap_dance(idx, &td);
reload_tap_dance();
break;
}
#endif
#ifdef VIAL_COMBO_ENABLE
case dynamic_vial_combo_get: {
uint8_t idx = msg[3];
vial_combo_entry_t entry = { 0 };
msg[0] = dynamic_keymap_get_combo(idx, &entry);
memcpy(&msg[1], &entry, sizeof(entry));
break;
}
case dynamic_vial_combo_set: {
uint8_t idx = msg[3];
vial_combo_entry_t entry;
memcpy(&entry, &msg[4], sizeof(entry));
msg[0] = dynamic_keymap_set_combo(idx, &entry);
break;
}
#endif
}
break;
}
}
}
#ifdef VIAL_ENCODERS_ENABLE
uint16_t g_vial_magic_keycode_override;
static void exec_keycode(uint16_t keycode) {
#ifdef VIAL_ENCODER_SIMPLE_TAP
register_code16(keycode);
#if VIAL_ENCODER_KEYCODE_DELAY > 0
wait_ms(VIAL_ENCODER_KEYCODE_DELAY);
#endif
unregister_code16(keycode);
#else
static void vial_keycode_down(uint16_t keycode) {
g_vial_magic_keycode_override = keycode;
keyrecord_t record = {.event = (keyevent_t){.key = { VIAL_ENCODER_MATRIX_MAGIC, VIAL_ENCODER_MATRIX_MAGIC }, .pressed = true, .time = (timer_read() | 1)}};
if (keycode <= QK_MODS_MAX)
if (keycode <= QK_MODS_MAX) {
register_code16(keycode);
else
process_record_quantum_helper(keycode, &record);
} else {
action_exec((keyevent_t){
.key = (keypos_t){.row = VIAL_MATRIX_MAGIC, .col = VIAL_MATRIX_MAGIC}, .pressed = 1, .time = (timer_read() | 1) /* time should not be 0 */
});
}
}
static void vial_keycode_up(uint16_t keycode) {
g_vial_magic_keycode_override = keycode;
if (keycode <= QK_MODS_MAX) {
unregister_code16(keycode);
} else {
action_exec((keyevent_t){
.key = (keypos_t){.row = VIAL_MATRIX_MAGIC, .col = VIAL_MATRIX_MAGIC}, .pressed = 0, .time = (timer_read() | 1) /* time should not be 0 */
});
}
}
static void vial_keycode_tap(uint16_t keycode) __attribute__((unused));
static void vial_keycode_tap(uint16_t keycode) {
vial_keycode_down(keycode);
qs_wait_ms(QS_tap_code_delay);
vial_keycode_up(keycode);
}
#ifdef VIAL_ENCODERS_ENABLE
static void exec_keycode(uint16_t keycode) {
vial_keycode_down(keycode);
#if VIAL_ENCODER_KEYCODE_DELAY > 0
wait_ms(VIAL_ENCODER_KEYCODE_DELAY);
#endif
record.event.time = timer_read() | 1;
record.event.pressed = false;
if (keycode <= QK_MODS_MAX)
unregister_code16(keycode);
else
process_record_quantum_helper(keycode, &record);
#endif
vial_keycode_up(keycode);
}
bool vial_encoder_update(uint8_t index, bool clockwise) {
@ -217,3 +322,193 @@ bool vial_encoder_update(uint8_t index, bool clockwise) {
return true;
}
#endif
#ifdef VIAL_TAP_DANCE_ENABLE
#include "process_tap_dance.h"
/* based on ZSA configurator generated code */
enum {
SINGLE_TAP = 1,
SINGLE_HOLD,
DOUBLE_TAP,
DOUBLE_HOLD,
DOUBLE_SINGLE_TAP,
MORE_TAPS
};
static uint8_t dance_state[VIAL_TAP_DANCE_ENTRIES];
static vial_tap_dance_entry_t td_entry;
static uint8_t dance_step(qk_tap_dance_state_t *state) {
if (state->count == 1) {
if (state->interrupted || !state->pressed) return SINGLE_TAP;
else return SINGLE_HOLD;
} else if (state->count == 2) {
if (state->interrupted) return DOUBLE_SINGLE_TAP;
else if (state->pressed) return DOUBLE_HOLD;
else return DOUBLE_TAP;
}
return MORE_TAPS;
}
static void on_dance(qk_tap_dance_state_t *state, void *user_data) {
uint8_t index = (uintptr_t)user_data;
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
return;
uint16_t kc = td_entry.on_tap;
if (kc) {
if (state->count == 3) {
vial_keycode_tap(kc);
vial_keycode_tap(kc);
vial_keycode_tap(kc);
} else if (state->count > 3) {
vial_keycode_tap(kc);
}
}
}
static void on_dance_finished(qk_tap_dance_state_t *state, void *user_data) {
uint8_t index = (uintptr_t)user_data;
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
return;
dance_state[index] = dance_step(state);
switch (dance_state[index]) {
case SINGLE_TAP: {
if (td_entry.on_tap)
vial_keycode_down(td_entry.on_tap);
break;
}
case SINGLE_HOLD: {
if (td_entry.on_hold)
vial_keycode_down(td_entry.on_hold);
else if (td_entry.on_tap)
vial_keycode_down(td_entry.on_tap);
break;
}
case DOUBLE_TAP: {
if (td_entry.on_double_tap) {
vial_keycode_down(td_entry.on_double_tap);
} else if (td_entry.on_tap) {
vial_keycode_tap(td_entry.on_tap);
vial_keycode_down(td_entry.on_tap);
}
break;
}
case DOUBLE_HOLD: {
if (td_entry.on_tap_hold) {
vial_keycode_down(td_entry.on_tap_hold);
} else {
if (td_entry.on_tap) {
vial_keycode_tap(td_entry.on_tap);
if (td_entry.on_hold)
vial_keycode_down(td_entry.on_hold);
else
vial_keycode_down(td_entry.on_tap);
} else if (td_entry.on_hold) {
vial_keycode_down(td_entry.on_hold);
}
}
break;
}
case DOUBLE_SINGLE_TAP: {
if (td_entry.on_tap) {
vial_keycode_tap(td_entry.on_tap);
vial_keycode_down(td_entry.on_tap);
}
break;
}
}
}
static void on_dance_reset(qk_tap_dance_state_t *state, void *user_data) {
uint8_t index = (uintptr_t)user_data;
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
return;
qs_wait_ms(QS_tap_code_delay);
uint8_t st = dance_state[index];
state->count = 0;
dance_state[index] = 0;
switch (st) {
case SINGLE_TAP: {
if (td_entry.on_tap)
vial_keycode_up(td_entry.on_tap);
break;
}
case SINGLE_HOLD: {
if (td_entry.on_hold)
vial_keycode_up(td_entry.on_hold);
else if (td_entry.on_tap)
vial_keycode_up(td_entry.on_tap);
break;
}
case DOUBLE_TAP: {
if (td_entry.on_double_tap) {
vial_keycode_up(td_entry.on_double_tap);
} else if (td_entry.on_tap) {
vial_keycode_up(td_entry.on_tap);
}
break;
}
case DOUBLE_HOLD: {
if (td_entry.on_tap_hold) {
vial_keycode_up(td_entry.on_tap_hold);
} else {
if (td_entry.on_tap) {
if (td_entry.on_hold)
vial_keycode_up(td_entry.on_hold);
else
vial_keycode_up(td_entry.on_tap);
} else if (td_entry.on_hold) {
vial_keycode_up(td_entry.on_hold);
}
}
break;
}
case DOUBLE_SINGLE_TAP: {
if (td_entry.on_tap) {
vial_keycode_up(td_entry.on_tap);
}
break;
}
}
}
qk_tap_dance_action_t tap_dance_actions[VIAL_TAP_DANCE_ENTRIES];
/* Load timings from eeprom into custom_tapping_term */
static void reload_tap_dance(void) {
for (size_t i = 0; i < VIAL_TAP_DANCE_ENTRIES; ++i) {
vial_tap_dance_entry_t td;
tap_dance_actions[i].fn.on_each_tap = on_dance;
tap_dance_actions[i].fn.on_dance_finished = on_dance_finished;
tap_dance_actions[i].fn.on_reset = on_dance_reset;
tap_dance_actions[i].user_data = (void*)i;
if (dynamic_keymap_get_tap_dance(i, &td) == 0) {
tap_dance_actions[i].custom_tapping_term = td.custom_tapping_term;
}
}
}
#endif
#ifdef VIAL_COMBO_ENABLE
combo_t key_combos[VIAL_COMBO_ENTRIES];
static void init_combo(void) {
for (size_t i = 0; i < VIAL_COMBO_ENTRIES; ++i) {
key_combos[i].keys = (void*)(uintptr_t)i;
}
}
void process_combo_event(uint16_t combo_index, bool pressed) {
vial_combo_entry_t entry;
if (dynamic_keymap_get_combo(combo_index, &entry) != 0)
return;
if (pressed)
vial_keycode_down(entry.output);
else
vial_keycode_up(entry.output);
}
#endif

View File

@ -19,8 +19,12 @@
#include <inttypes.h>
#include <stdbool.h>
#define VIAL_PROTOCOL_VERSION ((uint32_t)0x00000003)
#include "dynamic_keymap_eeprom.h"
#define VIAL_PROTOCOL_VERSION ((uint32_t)0x00000004)
#define VIAL_RAW_EPSIZE 32
void vial_init(void);
void vial_handle_cmd(uint8_t *data, uint8_t length);
#ifdef VIAL_ENCODERS_ENABLE
@ -40,7 +44,84 @@ enum {
vial_unlock_start = 0x06,
vial_unlock_poll = 0x07,
vial_lock = 0x08,
vial_qmk_settings_query = 0x09,
vial_qmk_settings_get = 0x0A,
vial_qmk_settings_set = 0x0B,
vial_qmk_settings_reset = 0x0C,
vial_dynamic_entry_op = 0x0D, /* operate on tapdance, combos, etc */
};
/* Fake encoder position in keyboard matrix, can't use 255 as that is immediately rejected by IS_NOEVENT */
#define VIAL_ENCODER_MATRIX_MAGIC 254
enum {
dynamic_vial_get_number_of_entries = 0x00,
dynamic_vial_tap_dance_get = 0x01,
dynamic_vial_tap_dance_set = 0x02,
dynamic_vial_combo_get = 0x03,
dynamic_vial_combo_set = 0x04,
};
/* Fake position in keyboard matrix, can't use 255 as that is immediately rejected by IS_NOEVENT
used to send arbitrary keycodes thru process_record_quantum_helper */
#define VIAL_MATRIX_MAGIC 254
#ifdef TAP_DANCE_ENABLE
#define VIAL_TAP_DANCE_ENABLE
#ifndef VIAL_TAP_DANCE_ENTRIES
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 4000
#define VIAL_TAP_DANCE_ENTRIES 32
#elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 2000
#define VIAL_TAP_DANCE_ENTRIES 16
#elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 1000
#define VIAL_TAP_DANCE_ENTRIES 8
#else
#define VIAL_TAP_DANCE_ENTRIES 4
#endif
#endif
typedef struct {
uint16_t on_tap;
uint16_t on_hold;
uint16_t on_double_tap;
uint16_t on_tap_hold;
uint16_t custom_tapping_term;
} vial_tap_dance_entry_t;
_Static_assert(sizeof(vial_tap_dance_entry_t) == 10, "Unexpected size of the vial_tap_dance_entry_t structure");
#else
#undef VIAL_TAP_DANCE_ENTRIES
#define VIAL_TAP_DANCE_ENTRIES 0
#endif
#ifdef COMBO_ENABLE
#define VIAL_COMBO_ENABLE
#ifndef VIAL_COMBO_ENTRIES
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 4000
#define VIAL_COMBO_ENTRIES 32
#elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 2000
#define VIAL_COMBO_ENTRIES 16
#elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 1000
#define VIAL_COMBO_ENTRIES 8
#else
#define VIAL_COMBO_ENTRIES 4
#endif
#endif
typedef struct {
uint16_t input[4];
uint16_t output;
} vial_combo_entry_t;
_Static_assert(sizeof(vial_combo_entry_t) == 10, "Unexpected size of the vial_combo_entry_t structure");
/* also to catch wrong include order in e.g. process_combo.h */
#ifdef COMBO_COUNT
#error COMBO_COUNT redefined - define VIAL_COMBO_ENTRIES instead
#endif
#define COMBO_COUNT VIAL_COMBO_ENTRIES
#else
#undef VIAL_COMBO_ENTRIES
#define VIAL_COMBO_ENTRIES 0
#endif

189
quantum/vialrgb.c Normal file
View File

@ -0,0 +1,189 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Based on https://github.com/qmk/qmk_firmware/pull/13036 */
#include "vialrgb.h"
#include <inttypes.h>
#include <string.h>
#include "rgb_matrix.h"
#include "vial.h"
typedef struct {
uint16_t vialrgb_id;
uint16_t qmk_id;
} vialrgb_supported_mode_t;
#include "vialrgb_effects.inc"
#define SUPPORTED_MODES_LENGTH (sizeof(supported_modes)/sizeof(*supported_modes))
#ifdef RGB_MATRIX_EFFECT_VIALRGB_DIRECT
HSV g_direct_mode_colors[DRIVER_LED_TOTAL];
#endif
static void get_supported(uint8_t *args, uint8_t length) {
/* retrieve supported effects (VialRGB IDs) with ID > gt */
uint16_t gt;
memcpy(&gt, args, sizeof(gt));
memset(args, 0xFF, length);
for (size_t i = 0; i < SUPPORTED_MODES_LENGTH; ++i) {
uint16_t id = pgm_read_word(&supported_modes[i].vialrgb_id);
if (id > gt && length >= sizeof(id)) {
memcpy(args, &id, sizeof(id));
length -= sizeof(id);
args += sizeof(id);
}
}
}
static uint16_t qmk_id_to_vialrgb_id(uint16_t id) {
for (size_t i = 0; i < SUPPORTED_MODES_LENGTH; ++i) {
uint16_t qmk_id = pgm_read_word(&supported_modes[i].qmk_id);
uint16_t vialrgb_id = pgm_read_word(&supported_modes[i].vialrgb_id);
if (qmk_id == id)
return vialrgb_id;
}
return 0;
}
static uint16_t vialrgb_id_to_qmk_id(uint16_t id) {
for (size_t i = 0; i < SUPPORTED_MODES_LENGTH; ++i) {
uint16_t qmk_id = pgm_read_word(&supported_modes[i].qmk_id);
uint16_t vialrgb_id = pgm_read_word(&supported_modes[i].vialrgb_id);
if (vialrgb_id == id)
return qmk_id;
}
return 0;
}
static uint16_t get_mode(void) {
/* Get current mode as vialrgb ID */
if (!rgb_matrix_is_enabled())
return VIALRGB_EFFECT_OFF;
return qmk_id_to_vialrgb_id(rgb_matrix_get_mode());
}
static void set_mode(uint16_t mode) {
/* Set a mode as vialrgb ID */
if (mode == VIALRGB_EFFECT_OFF) {
rgb_matrix_disable_noeeprom();
} else {
rgb_matrix_enable_noeeprom();
rgb_matrix_mode_noeeprom(vialrgb_id_to_qmk_id(mode));
}
}
#ifdef RGB_MATRIX_EFFECT_VIALRGB_DIRECT
static void get_matrix_pos_for_led(uint16_t led, uint8_t *output) {
/* reset initially so if we cannot locate the led, it's considered not part of kb matrix */
output[0] = output[1] = 0xFF;
/* this is kinda O(n^2) but what can you do */
for (size_t row = 0; row < MATRIX_ROWS; ++row)
for (size_t col = 0; col < MATRIX_COLS; ++col)
if (g_led_config.matrix_co[row][col] == led) {
output[0] = row;
output[1] = col;
return;
}
}
static void fast_set_leds(uint8_t *args, size_t length) {
/* Set multiple leds HSV, first 2 bytes are index of the first led, then number of leds, followed by HSV for the leds */
/* we have 32-2-2-1=27 total bytes available, so can set up to 9 leds per packet */
if (length < 3) return;
uint16_t first_index = args[0] | (args[1] << 8);
uint8_t num_leds = args[2];
length -= 3;
args += 3;
if (num_leds * 3 > length) return;
for (size_t i = 0; i < num_leds; ++i) {
if (i + first_index >= DRIVER_LED_TOTAL)
break;
g_direct_mode_colors[i + first_index].h = args[i * 3 + 0];
g_direct_mode_colors[i + first_index].s = args[i * 3 + 1];
uint8_t val = args[i * 3 + 2];
g_direct_mode_colors[i + first_index].v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val;
}
}
#endif
void vialrgb_get_value(uint8_t *data, uint8_t length) {
if (length != VIAL_RAW_EPSIZE) return;
/* data[0] is used by VIA command id */
uint8_t cmd = data[1];
uint8_t *args = &data[2];
switch (cmd) {
case vialrgb_get_info:
args[0] = VIALRGB_PROTOCOL_VERSION & 0xFF;
args[1] = VIALRGB_PROTOCOL_VERSION >> 8;
args[2] = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
break;
case vialrgb_get_mode: {
uint16_t vialrgb_id = get_mode();
args[0] = vialrgb_id & 0xFF;
args[1] = vialrgb_id >> 8;
args[2] = rgb_matrix_get_speed();
args[3] = rgb_matrix_get_hue();
args[4] = rgb_matrix_get_sat();
args[5] = rgb_matrix_get_val();
break;
}
case vialrgb_get_supported: {
get_supported(args, length - 2);
break;
}
#ifdef RGB_MATRIX_EFFECT_VIALRGB_DIRECT
case vialrgb_get_number_leds: {
args[0] = DRIVER_LED_TOTAL & 0xFF;
args[1] = DRIVER_LED_TOTAL >> 8;
break;
}
case vialrgb_get_led_info: {
uint16_t led = (args[0] & 0xFF) | (args[1] >> 8);
if (led >= DRIVER_LED_TOTAL) return;
// x, y
args[0] = g_led_config.point[led].x;
args[1] = g_led_config.point[led].y;
// flags
args[2] = g_led_config.flags[led];
// position in keyboard matrix (if it's keyboard LED, otherwise 0xFF)
get_matrix_pos_for_led(led, &args[3]);
break;
}
#endif
}
}
void vialrgb_set_value(uint8_t *data, uint8_t length) {
if (length != VIAL_RAW_EPSIZE) return;
/* data[0] is used by VIA command id */
uint8_t cmd = data[1];
uint8_t *args = &data[2];
switch (cmd) {
case vialrgb_set_mode: {
uint16_t vialrgb_id = args[0] | (args[1] << 8);
set_mode(vialrgb_id);
rgb_matrix_set_speed_noeeprom(args[2]);
rgb_matrix_sethsv_noeeprom(args[3], args[4], args[5]);
break;
}
#ifdef RGB_MATRIX_EFFECT_VIALRGB_DIRECT
case vialrgb_direct_fastset: {
fast_set_leds(args, length);
break;
}
#endif
}
}
void vialrgb_save(uint8_t *data, uint8_t length) {
(void)data;
(void)length;
eeconfig_update_rgb_matrix();
}

28
quantum/vialrgb.h Normal file
View File

@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#define VIALRGB_PROTOCOL_VERSION 1
/* Start at 0x40 in order to not conflict with existing "enum via_lighting_value",
even though they likely wouldn't be enabled together with vialrgb */
enum {
vialrgb_set_mode = 0x41,
vialrgb_direct_fastset = 0x42,
};
enum {
vialrgb_get_info = 0x40,
vialrgb_get_mode = 0x41,
vialrgb_get_supported = 0x42,
vialrgb_get_number_leds = 0x43,
vialrgb_get_led_info = 0x44,
};
void vialrgb_get_value(uint8_t *data, uint8_t length);
void vialrgb_set_value(uint8_t *data, uint8_t length);
void vialrgb_save(uint8_t *data, uint8_t length);
#if defined(VIALRGB_ENABLE) && !defined(RGB_MATRIX_ENABLE)
#error VIALRGB_ENABLE=yes requires RGB_MATRIX_ENABLE=yes
#endif

178
quantum/vialrgb_effects.inc Normal file
View File

@ -0,0 +1,178 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Note - never reorder or remove these, only add new animations at the end */
enum {
VIALRGB_EFFECT_OFF = 0,
VIALRGB_EFFECT_DIRECT,
VIALRGB_EFFECT_SOLID_COLOR,
VIALRGB_EFFECT_ALPHAS_MODS,
VIALRGB_EFFECT_GRADIENT_UP_DOWN,
VIALRGB_EFFECT_GRADIENT_LEFT_RIGHT,
VIALRGB_EFFECT_BREATHING,
VIALRGB_EFFECT_BAND_SAT,
VIALRGB_EFFECT_BAND_VAL,
VIALRGB_EFFECT_BAND_PINWHEEL_SAT,
VIALRGB_EFFECT_BAND_PINWHEEL_VAL,
VIALRGB_EFFECT_BAND_SPIRAL_SAT,
VIALRGB_EFFECT_BAND_SPIRAL_VAL,
VIALRGB_EFFECT_CYCLE_ALL,
VIALRGB_EFFECT_CYCLE_LEFT_RIGHT,
VIALRGB_EFFECT_CYCLE_UP_DOWN,
VIALRGB_EFFECT_RAINBOW_MOVING_CHEVRON,
VIALRGB_EFFECT_CYCLE_OUT_IN,
VIALRGB_EFFECT_CYCLE_OUT_IN_DUAL,
VIALRGB_EFFECT_CYCLE_PINWHEEL,
VIALRGB_EFFECT_CYCLE_SPIRAL,
VIALRGB_EFFECT_DUAL_BEACON,
VIALRGB_EFFECT_RAINBOW_BEACON,
VIALRGB_EFFECT_RAINBOW_PINWHEELS,
VIALRGB_EFFECT_RAINDROPS,
VIALRGB_EFFECT_JELLYBEAN_RAINDROPS,
VIALRGB_EFFECT_HUE_BREATHING,
VIALRGB_EFFECT_HUE_PENDULUM,
VIALRGB_EFFECT_HUE_WAVE,
VIALRGB_EFFECT_TYPING_HEATMAP,
VIALRGB_EFFECT_DIGITAL_RAIN,
VIALRGB_EFFECT_SOLID_REACTIVE_SIMPLE,
VIALRGB_EFFECT_SOLID_REACTIVE,
VIALRGB_EFFECT_SOLID_REACTIVE_WIDE,
VIALRGB_EFFECT_SOLID_REACTIVE_MULTIWIDE,
VIALRGB_EFFECT_SOLID_REACTIVE_CROSS,
VIALRGB_EFFECT_SOLID_REACTIVE_MULTICROSS,
VIALRGB_EFFECT_SOLID_REACTIVE_NEXUS,
VIALRGB_EFFECT_SOLID_REACTIVE_MULTINEXUS,
VIALRGB_EFFECT_SPLASH,
VIALRGB_EFFECT_MULTISPLASH,
VIALRGB_EFFECT_SOLID_SPLASH,
VIALRGB_EFFECT_SOLID_MULTISPLASH,
};
static const PROGMEM vialrgb_supported_mode_t supported_modes[] = {
{ VIALRGB_EFFECT_OFF, 0 },
#ifdef RGB_MATRIX_EFFECT_VIALRGB_DIRECT
{ VIALRGB_EFFECT_DIRECT, RGB_MATRIX_VIALRGB_DIRECT },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_COLOR
{ VIALRGB_EFFECT_SOLID_COLOR, RGB_MATRIX_SOLID_COLOR },
#endif
#ifdef RGB_MATRIX_EFFECT_ALPHAS_MODS
{ VIALRGB_EFFECT_ALPHAS_MODS, RGB_MATRIX_ALPHAS_MODS },
#endif
#ifdef RGB_MATRIX_EFFECT_GRADIENT_UP_DOWN
{ VIALRGB_EFFECT_GRADIENT_UP_DOWN, RGB_MATRIX_GRADIENT_UP_DOWN },
#endif
#ifdef RGB_MATRIX_EFFECT_GRADIENT_LEFT_RIGHT
{ VIALRGB_EFFECT_GRADIENT_LEFT_RIGHT, RGB_MATRIX_GRADIENT_LEFT_RIGHT },
#endif
#ifdef RGB_MATRIX_EFFECT_BREATHING
{ VIALRGB_EFFECT_BREATHING, RGB_MATRIX_BREATHING },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_SAT
{ VIALRGB_EFFECT_BAND_SAT, RGB_MATRIX_BAND_SAT },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_VAL
{ VIALRGB_EFFECT_BAND_VAL, RGB_MATRIX_BAND_VAL },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_PINWHEEL_SAT
{ VIALRGB_EFFECT_BAND_PINWHEEL_SAT, RGB_MATRIX_BAND_PINWHEEL_SAT },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_PINWHEEL_VAL
{ VIALRGB_EFFECT_BAND_PINWHEEL_VAL, RGB_MATRIX_BAND_PINWHEEL_VAL },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_SPIRAL_SAT
{ VIALRGB_EFFECT_BAND_SPIRAL_SAT, RGB_MATRIX_BAND_SPIRAL_SAT },
#endif
#ifdef RGB_MATRIX_EFFECT_BAND_SPIRAL_VAL
{ VIALRGB_EFFECT_BAND_SPIRAL_VAL, RGB_MATRIX_BAND_SPIRAL_VAL },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_ALL
{ VIALRGB_EFFECT_CYCLE_ALL, RGB_MATRIX_CYCLE_ALL },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_LEFT_RIGHT
{ VIALRGB_EFFECT_CYCLE_LEFT_RIGHT, RGB_MATRIX_CYCLE_LEFT_RIGHT },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_UP_DOWN
{ VIALRGB_EFFECT_CYCLE_UP_DOWN, RGB_MATRIX_CYCLE_UP_DOWN },
#endif
#ifdef RGB_MATRIX_EFFECT_RAINBOW_MOVING_CHEVRON
{ VIALRGB_EFFECT_RAINBOW_MOVING_CHEVRON, RGB_MATRIX_RAINBOW_MOVING_CHEVRON },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_OUT_IN
{ VIALRGB_EFFECT_CYCLE_OUT_IN, RGB_MATRIX_CYCLE_OUT_IN },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_OUT_IN_DUAL
{ VIALRGB_EFFECT_CYCLE_OUT_IN_DUAL, RGB_MATRIX_CYCLE_OUT_IN_DUAL },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_PINWHEEL
{ VIALRGB_EFFECT_CYCLE_PINWHEEL, RGB_MATRIX_CYCLE_PINWHEEL },
#endif
#ifdef RGB_MATRIX_EFFECT_CYCLE_SPIRAL
{ VIALRGB_EFFECT_CYCLE_SPIRAL, RGB_MATRIX_CYCLE_SPIRAL },
#endif
#ifdef RGB_MATRIX_EFFECT_DUAL_BEACON
{ VIALRGB_EFFECT_DUAL_BEACON, RGB_MATRIX_DUAL_BEACON },
#endif
#ifdef RGB_MATRIX_EFFECT_RAINBOW_BEACON
{ VIALRGB_EFFECT_RAINBOW_BEACON, RGB_MATRIX_RAINBOW_BEACON },
#endif
#ifdef RGB_MATRIX_EFFECT_RAINBOW_PINWHEELS
{ VIALRGB_EFFECT_RAINBOW_PINWHEELS, RGB_MATRIX_RAINBOW_PINWHEELS },
#endif
#ifdef RGB_MATRIX_EFFECT_RAINDROPS
{ VIALRGB_EFFECT_RAINDROPS, RGB_MATRIX_RAINDROPS },
#endif
#ifdef RGB_MATRIX_EFFECT_JELLYBEAN_RAINDROPS
{ VIALRGB_EFFECT_JELLYBEAN_RAINDROPS, RGB_MATRIX_JELLYBEAN_RAINDROPS },
#endif
#ifdef RGB_MATRIX_EFFECT_HUE_BREATHING
{ VIALRGB_EFFECT_HUE_BREATHING, RGB_MATRIX_HUE_BREATHING },
#endif
#ifdef RGB_MATRIX_EFFECT_HUE_PENDULUM
{ VIALRGB_EFFECT_HUE_PENDULUM, RGB_MATRIX_HUE_PENDULUM },
#endif
#ifdef RGB_MATRIX_EFFECT_HUE_WAVE
{ VIALRGB_EFFECT_HUE_WAVE, RGB_MATRIX_HUE_WAVE },
#endif
#ifdef RGB_MATRIX_EFFECT_TYPING_HEATMAP
{ VIALRGB_EFFECT_TYPING_HEATMAP, RGB_MATRIX_TYPING_HEATMAP },
#endif
#ifdef RGB_MATRIX_EFFECT_DIGITAL_RAIN
{ VIALRGB_EFFECT_DIGITAL_RAIN, RGB_MATRIX_DIGITAL_RAIN },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_SIMPLE
{ VIALRGB_EFFECT_SOLID_REACTIVE_SIMPLE, RGB_MATRIX_SOLID_REACTIVE_SIMPLE },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE
{ VIALRGB_EFFECT_SOLID_REACTIVE, RGB_MATRIX_SOLID_REACTIVE },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_WIDE
{ VIALRGB_EFFECT_SOLID_REACTIVE_WIDE, RGB_MATRIX_SOLID_REACTIVE_WIDE },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTIWIDE
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTIWIDE, RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_CROSS
{ VIALRGB_EFFECT_SOLID_REACTIVE_CROSS, RGB_MATRIX_SOLID_REACTIVE_CROSS },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTICROSS
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTICROSS, RGB_MATRIX_SOLID_REACTIVE_MULTICROSS },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_NEXUS
{ VIALRGB_EFFECT_SOLID_REACTIVE_NEXUS, RGB_MATRIX_SOLID_REACTIVE_NEXUS },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_REACTIVE_MULTINEXUS
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTINEXUS, RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS },
#endif
#ifdef RGB_MATRIX_EFFECT_SPLASH
{ VIALRGB_EFFECT_SPLASH, RGB_MATRIX_SPLASH },
#endif
#ifdef RGB_MATRIX_EFFECT_MULTISPLASH
{ VIALRGB_EFFECT_MULTISPLASH, RGB_MATRIX_MULTISPLASH },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_SPLASH
{ VIALRGB_EFFECT_SOLID_SPLASH, RGB_MATRIX_SOLID_SPLASH },
#endif
#ifdef RGB_MATRIX_EFFECT_SOLID_MULTISPLASH
{ VIALRGB_EFFECT_SOLID_MULTISPLASH, RGB_MATRIX_SOLID_MULTISPLASH },
#endif
};

View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_util.h"
#include "action.h"
#include "wait.h"
#include "qmk_settings.h"
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
@ -55,12 +56,6 @@ __attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrec
__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; }
#endif
#ifndef TAP_CODE_DELAY
# define TAP_CODE_DELAY 0
#endif
#ifndef TAP_HOLD_CAPS_DELAY
# define TAP_HOLD_CAPS_DELAY 80
#endif
/** \brief Called to execute an action.
*
* FIXME: Needs documentation.
@ -90,7 +85,7 @@ void action_exec(keyevent_t event) {
keyrecord_t record = {.event = event};
#ifndef NO_ACTION_ONESHOT
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (QS_oneshot_timeout > 0) {
if (has_oneshot_layer_timed_out()) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
@ -102,7 +97,7 @@ void action_exec(keyevent_t event) {
clear_oneshot_swaphands();
}
# endif
# endif
}
#endif
#ifndef NO_ACTION_TAPPING
@ -301,13 +296,11 @@ void process_action(keyrecord_t *record, action_t action) {
} else if (tap_count == 1) {
dprint("MODS_TAP: Oneshot: start\n");
set_oneshot_mods(mods | get_oneshot_mods());
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
} else if (QS_oneshot_tap_toggle > 1 && tap_count == QS_oneshot_tap_toggle) {
dprint("MODS_TAP: Toggling oneshot");
clear_oneshot_mods();
set_oneshot_locked_mods(mods);
register_mods(mods);
# endif
} else {
register_mods(mods | get_oneshot_mods());
}
@ -317,15 +310,15 @@ void process_action(keyrecord_t *record, action_t action) {
unregister_mods(mods);
} else if (tap_count == 1) {
// Retain Oneshot mods
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
if (QS_oneshot_tap_toggle > 1) {
if (mods & get_mods()) {
clear_oneshot_locked_mods();
clear_oneshot_mods();
unregister_mods(mods);
}
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
}
} else if (QS_oneshot_tap_toggle > 1 && tap_count == QS_oneshot_tap_toggle) {
// Toggle Oneshot Layer
# endif
} else {
clear_oneshot_mods();
unregister_mods(mods);
@ -371,9 +364,9 @@ void process_action(keyrecord_t *record, action_t action) {
if (tap_count > 0) {
dprint("MODS_TAP: Tap: unregister_code\n");
if (action.layer_tap.code == KC_CAPS) {
wait_ms(TAP_HOLD_CAPS_DELAY);
qs_wait_ms(QS_tap_hold_caps_delay);
} else {
wait_ms(TAP_CODE_DELAY);
qs_wait_ms(QS_tap_code_delay);
}
unregister_code(action.key.code);
} else {
@ -547,7 +540,7 @@ void process_action(keyrecord_t *record, action_t action) {
# ifndef NO_ACTION_ONESHOT
case OP_ONESHOT:
// Oneshot modifier
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
if (QS_oneshot_tap_toggle > 1) {
do_release_oneshot = false;
if (event.pressed) {
del_mods(get_oneshot_locked_mods());
@ -555,13 +548,13 @@ void process_action(keyrecord_t *record, action_t action) {
reset_oneshot_layer();
layer_off(action.layer_tap.val);
break;
} else if (tap_count < ONESHOT_TAP_TOGGLE) {
} else if (tap_count < QS_oneshot_tap_toggle) {
layer_on(action.layer_tap.val);
set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
}
} else {
add_mods(get_oneshot_locked_mods());
if (tap_count >= ONESHOT_TAP_TOGGLE) {
if (tap_count >= QS_oneshot_tap_toggle) {
reset_oneshot_layer();
clear_oneshot_locked_mods();
set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
@ -569,7 +562,7 @@ void process_action(keyrecord_t *record, action_t action) {
clear_oneshot_layer_state(ONESHOT_PRESSED);
}
}
# else
} else {
if (event.pressed) {
layer_on(action.layer_tap.val);
set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
@ -579,7 +572,7 @@ void process_action(keyrecord_t *record, action_t action) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
}
# endif
}
break;
# endif
default:
@ -596,9 +589,9 @@ void process_action(keyrecord_t *record, action_t action) {
if (tap_count > 0) {
dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
if (action.layer_tap.code == KC_CAPS) {
wait_ms(TAP_HOLD_CAPS_DELAY);
qs_wait_ms(QS_tap_hold_caps_delay);
} else {
wait_ms(TAP_CODE_DELAY);
qs_wait_ms(QS_tap_code_delay);
}
unregister_code(action.layer_tap.code);
} else {
@ -677,7 +670,7 @@ void process_action(keyrecord_t *record, action_t action) {
if (event.pressed) {
register_code(action.swap.code);
} else {
wait_ms(TAP_CODE_DELAY);
qs_wait_ms(QS_tap_code_delay);
unregister_code(action.swap.code);
*record = (keyrecord_t){}; // hack: reset tap mode
}
@ -933,7 +926,7 @@ void tap_code_delay(uint8_t code, uint16_t delay) {
*
* \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
*/
void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? QS_tap_hold_caps_delay : QS_tap_code_delay); }
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
*

View File

@ -10,6 +10,10 @@
# include "nodebug.h"
#endif
#ifdef VIAL_ENABLE
#include "vial.h"
#endif
/** \brief Default Layer State
*/
layer_state_t default_layer_state = 0;
@ -192,6 +196,10 @@ uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS]
* Updates the cached keys when changing layers
*/
void update_source_layers_cache(keypos_t key, uint8_t layer) {
#ifdef VIAL_ENABLE
if (key.row == VIAL_MATRIX_MAGIC) return;
#endif
const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
const uint8_t storage_row = key_number / 8;
const uint8_t storage_bit = key_number % 8;
@ -206,6 +214,10 @@ void update_source_layers_cache(keypos_t key, uint8_t layer) {
* reads the cached keys stored when the layer was changed
*/
uint8_t read_source_layers_cache(keypos_t key) {
#ifdef VIAL_ENABLE
if (key.row == VIAL_MATRIX_MAGIC) return 0;
#endif
const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
const uint8_t storage_row = key_number / 8;
const uint8_t storage_bit = key_number % 8;

View File

@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_layer.h"
#include "timer.h"
#include "keycode_config.h"
#include "qmk_settings.h"
extern keymap_config_t keymap_config;
@ -62,12 +63,8 @@ void clear_oneshot_locked_mods(void) {
oneshot_locked_mods_changed_kb(oneshot_locked_mods);
}
}
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static uint16_t oneshot_time = 0;
bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; }
# else
bool has_oneshot_mods_timed_out(void) { return false; }
# endif
bool has_oneshot_mods_timed_out(void) { return QS_oneshot_timeout > 0 && TIMER_DIFF_16(timer_read(), oneshot_time) >= QS_oneshot_timeout; }
#endif
/* oneshot layer */
@ -92,26 +89,22 @@ enum {
} swap_hands_oneshot = SHO_OFF;
# endif
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static uint16_t oneshot_layer_time = 0;
inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); }
inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= QS_oneshot_timeout && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); }
# ifdef SWAP_HANDS_ENABLE
static uint16_t oneshot_swaphands_time = 0;
inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); }
inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= QS_oneshot_timeout && (swap_hands_oneshot == SHO_ACTIVE); }
# endif
# endif
# ifdef SWAP_HANDS_ENABLE
void set_oneshot_swaphands(void) {
swap_hands_oneshot = SHO_PRESSED;
swap_hands = true;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_swaphands_time = timer_read();
if (oneshot_layer_time != 0) {
oneshot_layer_time = oneshot_swaphands_time;
}
# endif
}
void release_oneshot_swaphands(void) {
@ -135,9 +128,7 @@ void use_oneshot_swaphands(void) {
void clear_oneshot_swaphands(void) {
swap_hands_oneshot = SHO_OFF;
swap_hands = false;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_swaphands_time = 0;
# endif
}
# endif
@ -150,9 +141,7 @@ void set_oneshot_layer(uint8_t layer, uint8_t state) {
if (!keymap_config.oneshot_disable) {
oneshot_layer_data = layer << 3 | state;
layer_on(layer);
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = timer_read();
# endif
oneshot_layer_changed_kb(get_oneshot_layer());
} else {
layer_on(layer);
@ -164,9 +153,7 @@ void set_oneshot_layer(uint8_t layer, uint8_t state) {
*/
void reset_oneshot_layer(void) {
oneshot_layer_data = 0;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = 0;
# endif
oneshot_layer_changed_kb(get_oneshot_layer());
}
/** \brief Clear oneshot layer
@ -231,12 +218,10 @@ void send_keyboard_report(void) {
keyboard_report->mods |= macro_mods;
#ifndef NO_ACTION_ONESHOT
if (oneshot_mods) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_mods_timed_out()) {
if (QS_oneshot_timeout > 0 && has_oneshot_mods_timed_out()) {
dprintf("Oneshot: timeout\n");
clear_oneshot_mods();
}
# endif
keyboard_report->mods |= oneshot_mods;
if (has_anykey(keyboard_report)) {
clear_oneshot_mods();
@ -335,9 +320,7 @@ uint8_t get_oneshot_mods(void) { return oneshot_mods; }
void add_oneshot_mods(uint8_t mods) {
if ((oneshot_mods & mods) != mods) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = timer_read();
# endif
oneshot_mods |= mods;
oneshot_mods_changed_kb(mods);
}
@ -346,9 +329,7 @@ void add_oneshot_mods(uint8_t mods) {
void del_oneshot_mods(uint8_t mods) {
if (oneshot_mods & mods) {
oneshot_mods &= ~mods;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = oneshot_mods ? timer_read() : 0;
# endif
oneshot_mods_changed_kb(oneshot_mods);
}
}
@ -360,9 +341,7 @@ void del_oneshot_mods(uint8_t mods) {
void set_oneshot_mods(uint8_t mods) {
if (!keymap_config.oneshot_disable) {
if (oneshot_mods != mods) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = timer_read();
# endif
oneshot_mods = mods;
oneshot_mods_changed_kb(mods);
}
@ -376,9 +355,7 @@ void set_oneshot_mods(uint8_t mods) {
void clear_oneshot_mods(void) {
if (oneshot_mods) {
oneshot_mods = 0;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = 0;
# endif
oneshot_mods_changed_kb(oneshot_mods);
}
}

View File

@ -21,18 +21,24 @@
#include <string.h>
#include "eeprom_stm32.h"
/* In-memory contents of emulated eeprom for faster access */
#define SNAPSHOT_START (FEE_BASE_ADDRESS)
#define SNAPSHOT_END (FEE_BASE_ADDRESS+FEE_SNAPSHOT_SIZE)
#define WRITELOG_START (SNAPSHOT_END)
#define WRITELOG_END (WRITELOG_START+FEE_WRITELOG_SIZE)
/* In-memory contents of emulated eeprom for direct faster access */
static uint8_t DataBuf[FEE_DENSITY_BYTES];
/* Pointer to the first available slot within flash area */
/* Pointer to the first available slot within the writelog */
static uint8_t *empty_slot;
void EEPROM_Init(void) {
memset(DataBuf, 0, sizeof(DataBuf));
/* First, load the snapshot directly from flash */
memcpy(DataBuf, (void*)FEE_BASE_ADDRESS, FEE_SNAPSHOT_SIZE);
/* Load emulated eeprom contents from flash into memory */
/* Then, process writelog to update DataBuf entries */
uint8_t *addr;
for (addr = (uint8_t*)FEE_PAGE_BASE_ADDRESS; addr < (uint8_t*)FEE_LAST_PAGE_ADDRESS; addr += 4) {
for (addr = (uint8_t*)WRITELOG_START; addr < (uint8_t*)WRITELOG_END; addr += 4) {
uint16_t address;
uint8_t value;
memcpy(&address, addr, sizeof(address));
@ -46,16 +52,20 @@ void EEPROM_Init(void) {
empty_slot = addr;
}
/* Clear flash contents (doesn't touch in-memory DataBuf) */
/* Erase flash contents so we can put updated data in (doesn't touch in-memory DataBuf) */
static void eeprom_clear(void) {
FLASH_Unlock();
for (uint32_t page_num = 0; page_num < FEE_DENSITY_PAGES; ++page_num)
FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE));
#if defined(EEPROM_EMU_STM32F4)
FLASH_ErasePage(FEE_SECTOR_ID);
#else
for (uint32_t erase_address = SNAPSHOT_START; erase_address < WRITELOG_END; erase_address += FEE_PAGE_SIZE)
FLASH_ErasePage(erase_address);
#endif
FLASH_Lock();
empty_slot = (void*)FEE_PAGE_BASE_ADDRESS;
empty_slot = (void*)WRITELOG_START;
}
/* Erase emulated eeprom */
@ -67,29 +77,28 @@ void EEPROM_Erase(void) {
static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte);
/* Dump in-memory contents into flash */
static void eeprom_restore(void) {
for (uint32_t i = 0; i < FEE_DENSITY_BYTES; ++i) {
/* don't bother writing zeroes */
if (DataBuf[i]) {
eeprom_writedatabyte(i, DataBuf[i]);
}
/* Dump in-memory eeprom contents into the snapshot area */
static void eeprom_write_snapshot(void) {
FLASH_Unlock();
for (uint32_t i = 0; i < FEE_DENSITY_BYTES; i += 2) {
uint16_t halfword;
memcpy(&halfword, &DataBuf[i], sizeof(halfword));
FLASH_ProgramHalfWord(SNAPSHOT_START + i, halfword);
}
FLASH_Lock();
}
static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte) {
/* if couldn't find an empty spot, we must re-initialize emulated eeprom */
if (empty_slot >= (uint8_t*)FEE_LAST_PAGE_ADDRESS) {
/* ensure that the following call to eeprom_restore will write our desired byte value */
DataBuf[Address] = DataByte;
if (empty_slot >= (uint8_t*)WRITELOG_END) {
/* fully erase emulated eeprom */
eeprom_clear();
/* and then write DataBuf contents back into flash */
eeprom_restore();
/* don't need to do anything else as eeprom_restore already wrote our value */
eeprom_write_snapshot();
return;
}
@ -106,7 +115,7 @@ static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte) {
empty_slot += 4;
}
void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
static void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
/* if the address is out-of-bounds, do nothing */
if (Address >= FEE_DENSITY_BYTES)
return;
@ -115,14 +124,14 @@ void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
if (DataBuf[Address] == DataByte)
return;
/* perform the write into flash memory */
eeprom_writedatabyte(Address, DataByte);
/* keep DataBuf cache in sync */
DataBuf[Address] = DataByte;
/* perform the write into flash memory */
eeprom_writedatabyte(Address, DataByte);
}
uint8_t EEPROM_ReadDataByte(uint16_t Address) {
static uint8_t EEPROM_ReadDataByte(uint16_t Address) {
uint8_t DataByte = 0x00;
if (Address < FEE_DENSITY_BYTES)

View File

@ -37,23 +37,30 @@
# define MCU_STM32F072CB
#elif defined(EEPROM_EMU_STM32F042x6)
# define MCU_STM32F042K6
#else
# error "not implemented."
#elif defined(EEPROM_EMU_STM32F411xC)
# define MCU_STM32F411xC
#endif
#ifndef EEPROM_PAGE_SIZE
/* The page_size * density_pages should provide 8k of space, split 4k/4k between snapshot and writelog in the default config */
#ifndef FEE_DENSITY_PAGES
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6)
# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte
# define FEE_DENSITY_PAGES 8 // How many pages are used
# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB)
# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte
# define FEE_DENSITY_PAGES 4 // How many pages are used
# elif defined(MCU_STM32F411xC)
# define FEE_PAGE_SIZE (uint32_t)0x20000 // Page size = 128KByte
# define FEE_DENSITY_PAGES 1 // How many pages are used
# define FEE_SECTOR_ID 5 // sector id of the flash
# else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
# error "No MCU type specified and FEE_DENSITY_PAGES not defined.\
Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)\
or define FEE_DENSITY_PAGES yourself."
# endif
#endif
#ifndef EEPROM_START_ADDRESS
#ifndef FEE_MCU_FLASH_SIZE
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB)
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
# elif defined(MCU_STM32F042K6)
@ -64,24 +71,35 @@
# define FEE_MCU_FLASH_SIZE 384 // Size in Kb
# elif defined(MCU_STM32F303CC)
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
# elif defined(MCU_STM32F411xC)
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
# else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
# error "No MCU type specified and FEE_MCU_FLASH_SIZE not defined.\
Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)\
or define FEE_MCU_FLASH_SIZE yourself."
# endif
#endif
/* Start of the emulated eeprom flash area */
#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
/* End of the emulated eeprom flash area */
#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
/* Size of emulated eeprom */
#define FEE_DENSITY_BYTES 1024
#ifndef FEE_BASE_ADDRESS
/* Start of the emulated eeprom flash area, place it at the end of the flash memory */
#define FEE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
#endif
#ifndef FEE_SNAPSHOT_SIZE
/* Size of eeprom snapshot, in bytes. This is equal to emulated eeprom size. */
#define FEE_SNAPSHOT_SIZE 4096
#endif
#ifndef FEE_WRITELOG_SIZE
/* Size of eeprom writelog, in bytes. By default, use all the remaining amount of flash bank. */
#define FEE_WRITELOG_SIZE (FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_SNAPSHOT_SIZE)
#endif
/* Flash word value after erase */
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
_Static_assert(FEE_DENSITY_PAGES * FEE_PAGE_SIZE >= FEE_DENSITY_BYTES * 8,
"flash memory for emulated eeprom is too small; for correct functionality ensure it is at least 8x FEE_DENSITY_BYTES");
/* Size of emulated eeprom */
#define FEE_DENSITY_BYTES FEE_SNAPSHOT_SIZE
void EEPROM_Init(void);
void EEPROM_Erase(void);
void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
uint8_t EEPROM_ReadDataByte(uint16_t Address);

View File

@ -16,28 +16,24 @@
* Modifications for QMK and STM32F303 by Yiancar
*/
#if defined(EEPROM_EMU_STM32F303xC)
# define STM32F303xC
# include "stm32f3xx.h"
#elif defined(EEPROM_EMU_STM32F103xB)
# define STM32F103xB
# include "stm32f1xx.h"
#elif defined(EEPROM_EMU_STM32F072xB)
# define STM32F072xB
# include "stm32f0xx.h"
#elif defined(EEPROM_EMU_STM32F042x6)
# define STM32F042x6
# include "stm32f0xx.h"
#else
# error "not implemented."
#endif
#include "flash_stm32.h"
#if defined(EEPROM_EMU_STM32F103xB)
# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#endif
#if defined(EEPROM_EMU_STM32F4)
# define FLASH_PSIZE_HFWORD FLASH_CR_PSIZE_0
# define FLASH_PSIZE_WORD FLASH_CR_PSIZE_1
# define FLASH_CR_SNB_POS 3
/* the flash key was not defined in the CMSIS used by current chibios */
# define FLASH_KEY1 0x45670123
# define FLASH_KEY2 0xCDEF89AB
# define FLASH_SR_FLAGS (FLASH_SR_PGAERR|FLASH_SR_PGPERR|FLASH_SR_PGSERR|FLASH_SR_WRPERR)
#else
# define FLASH_SR_FLAGS (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR)
#endif
/* Delay definition */
#define EraseTimeout ((uint32_t)0x00000FFF)
#define ProgramTimeout ((uint32_t)0x0000001F)
@ -64,11 +60,14 @@ static void delay(void) {
FLASH_Status FLASH_GetStatus(void) {
if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) return FLASH_BUSY;
#if defined(EEPROM_EMU_STM32F4)
if ((FLASH->SR & (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR))) return FLASH_ERROR_PG;
if ((FLASH->SR & FLASH_SR_WRPERR)) return FLASH_ERROR_WRP;
#else
if ((FLASH->SR & FLASH_SR_PGERR) != 0) return FLASH_ERROR_PG;
if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
#endif
return FLASH_COMPLETE;
}
@ -97,30 +96,41 @@ FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
/**
* @brief Erases a specified FLASH page.
* @param Page_Address: The page address to be erased.
* @param Page_Address: The page address or sector to be erased.
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
FLASH_Status status = FLASH_COMPLETE;
#ifndef EEPROM_EMU_STM32F4
/* Check the parameters */
ASSERT(IS_FLASH_ADDRESS(Page_Address));
#endif
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if (status == FLASH_COMPLETE) {
/* if the previous operation is completed, proceed to erase the page */
#if defined(EEPROM_EMU_STM32F4)
FLASH->CR &= ~FLASH_CR_SNB;
FLASH->CR |= FLASH_CR_SER | (Page_Address << FLASH_CR_SNB_POS);
#else
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = Page_Address;
#endif
FLASH->CR |= FLASH_CR_STRT;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if (status != FLASH_TIMEOUT) {
/* if the erase operation is completed, disable the PER Bit */
/* clear the SER or PER Bit */
#if defined(EEPROM_EMU_STM32F4)
FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
#else
FLASH->CR &= ~FLASH_CR_PER;
#endif
}
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
FLASH_ClearFlag(FLASH_SR_FLAGS);
}
/* Return the Erase Status */
return status;
@ -136,11 +146,15 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
FLASH_Status status = FLASH_BAD_ADDRESS;
if (IS_FLASH_ADDRESS(Address)) {
if (IS_FLASH_ADDRESS(Address) && (Address % sizeof(Data)) == 0) {
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if (status == FLASH_COMPLETE) {
/* if the previous operation is completed, proceed to program the new data */
#if defined(EEPROM_EMU_STM32F4)
FLASH->CR &= ~FLASH_CR_PSIZE;
FLASH->CR |= FLASH_PSIZE_HFWORD;
#endif
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
@ -149,7 +163,7 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
/* if the program operation is completed, disable the PG Bit */
FLASH->CR &= ~FLASH_CR_PG;
}
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
FLASH_ClearFlag(FLASH_SR_FLAGS);
}
}
return status;

View File

@ -22,6 +22,26 @@
extern "C" {
#endif
#if defined(EEPROM_EMU_STM32F303xC)
# define STM32F303xC
# include "stm32f3xx.h"
#elif defined(EEPROM_EMU_STM32F103xB)
# define STM32F103xB
# include "stm32f1xx.h"
#elif defined(EEPROM_EMU_STM32F072xB)
# define STM32F072xB
# include "stm32f0xx.h"
#elif defined(EEPROM_EMU_STM32F042x6)
# define STM32F042x6
# include "stm32f0xx.h"
#elif defined(EEPROM_EMU_STM32F411xC)
# define EEPROM_EMU_STM32F4
# define STM32F411xE
# include "stm32f4xx.h"
#else
# error "not implemented."
#endif
#include <ch.h>
#include <hal.h>

View File

@ -100,6 +100,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef EEPROM_DRIVER
# include "eeprom_driver.h"
#endif
#ifdef QMK_SETTINGS
# include "qmk_settings.h"
#endif
#ifdef VIAL_ENABLE
# include "vial.h"
#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
@ -242,6 +248,12 @@ void keyboard_setup(void) {
#endif
#ifdef EEPROM_DRIVER
eeprom_driver_init();
#endif
#ifdef VIAL_ENABLE
vial_init();
#endif
#ifdef QMK_SETTINGS
qmk_settings_init();
#endif
matrix_setup();
keyboard_pre_init_kb();