diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk
index 50411e952a8..ddbaa89432a 100644
--- a/builddefs/build_keyboard.mk
+++ b/builddefs/build_keyboard.mk
@@ -187,9 +187,9 @@ include $(COMMUNITY_RULES_MK)
ifneq ($(COMMUNITY_MODULES),)
-$(INTERMEDIATE_OUTPUT)/src/community_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
+$(INTERMEDIATE_OUTPUT)/src/community_post_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
- $(eval CMD=$(QMK_BIN) generate-community-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_config.h $(KEYMAP_JSON))
+ $(eval CMD=$(QMK_BIN) generate-community-post-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(KEYMAP_JSON))
@$(BUILD_CMD)
$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
@@ -227,10 +227,10 @@ $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc: $(KEYMAP_
$(eval CMD=$(QMK_BIN) generate-split-transaction-id-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc $(KEYMAP_JSON))
@$(BUILD_CMD)
-COMMUNITY_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_config.h
+COMMUNITY_POST_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_post_config.h
SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c
-generated-files: $(INTERMEDIATE_OUTPUT)/src/community_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
+generated-files: $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
endif
@@ -331,10 +331,6 @@ define config_h_community_module_appender
endef
$(foreach module,$(COMMUNITY_MODULE_PATHS),$(eval $(call config_h_community_module_appender,$(module))))
-ifneq ($(COMMUNITY_CONFIG_H),)
- CONFIG_H += $(COMMUNITY_CONFIG_H)
-endif
-
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","")
CONFIG_H += $(KEYBOARD_PATH_5)/config.h
endif
@@ -376,6 +372,10 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","")
POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h
endif
+ifneq ($(COMMUNITY_POST_CONFIG_H),)
+ POST_CONFIG_H += $(COMMUNITY_POST_CONFIG_H)
+endif
+
CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index b7cb2193fa3..b15d95654b2 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -98,26 +98,34 @@ endif
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
STENO_PROTOCOL ?= all
+
ifeq ($(strip $(STENO_ENABLE)), yes)
ifeq ($(filter $(STENO_PROTOCOL),$(VALID_STENO_PROTOCOL_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid STENO_PROTOCOL,STENO_PROTOCOL="$(STENO_PROTOCOL)" is not a valid stenography protocol)
- else
- OPT_DEFS += -DSTENO_ENABLE
+ endif
+
+ ifeq ($(strip $(PLOVER_HID_ENABLE)), yes)
+ $(call WARNING_MESSAGE, PLOVER_HID_ENABLE is mutually exclusive with STENO_ENABLE and will be disabled)
+ override PLOVER_HID_ENABLE = no
+ endif
+
+ ifeq ($(strip $(STENO_PROTOCOL)), all)
+ override STENO_PROTOCOL := $(filter-out all,$(VALID_STENO_PROTOCOL_TYPES))
+ OPT_DEFS += -DSTENO_ENABLE_ALL
+ endif
+
+ OPT_DEFS += -DNUM_STENO_PROTOCOLS=$(words $(sort $(STENO_PROTOCOL)))
+
+ # for each supported protocol -> add deps
+ ifneq ($(filter $(STENO_PROTOCOL),geminipr),)
+ OPT_DEFS += -DSTENO_ENABLE_GEMINI
+ SRC += $(QUANTUM_DIR)/steno/steno_gemini.c
+ VIRTSER_ENABLE ?= yes
+ endif
+ ifneq ($(filter $(STENO_PROTOCOL),txbolt),)
+ OPT_DEFS += -DSTENO_ENABLE_BOLT
+ SRC += $(QUANTUM_DIR)/steno/steno_bolt.c
VIRTSER_ENABLE ?= yes
-
- ifeq ($(strip $(STENO_PROTOCOL)), geminipr)
- OPT_DEFS += -DSTENO_ENABLE_GEMINI
- endif
- ifeq ($(strip $(STENO_PROTOCOL)), txbolt)
- OPT_DEFS += -DSTENO_ENABLE_BOLT
- endif
- ifeq ($(strip $(STENO_PROTOCOL)), all)
- OPT_DEFS += -DSTENO_ENABLE_ALL
- OPT_DEFS += -DSTENO_ENABLE_GEMINI
- OPT_DEFS += -DSTENO_ENABLE_BOLT
- endif
-
- SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
endif
endif
diff --git a/builddefs/generic_features.mk b/builddefs/generic_features.mk
index 6d394977bd0..56dc510d1f0 100644
--- a/builddefs/generic_features.mk
+++ b/builddefs/generic_features.mk
@@ -45,12 +45,14 @@ GENERIC_FEATURES = \
MOUSEKEY \
MUSIC \
OS_DETECTION \
+ PLOVER_HID \
PROGRAMMABLE_BUTTON \
REPEAT_KEY \
SECURE \
SEND_STRING \
SEQUENCER \
SPACE_CADET \
+ STENO \
SWAP_HANDS \
TAP_DANCE \
TRI_LAYER \
diff --git a/builddefs/show_options.mk b/builddefs/show_options.mk
index 1c1a3ebf8e0..ab1208ae83f 100644
--- a/builddefs/show_options.mk
+++ b/builddefs/show_options.mk
@@ -63,6 +63,7 @@ OTHER_OPTION_NAMES = \
LCD_BACKLIGHT_ENABLE \
MACROS_ENABLED \
PS2_ENABLE \
+ PLOVER_HID_ENABLE \
PS2_MOUSE_ENABLE \
PS2_DRIVER \
RAW_ENABLE \
diff --git a/data/constants/keycodes/keycodes_0.0.9.hjson b/data/constants/keycodes/keycodes_0.0.9.hjson
new file mode 100644
index 00000000000..15925f35410
--- /dev/null
+++ b/data/constants/keycodes/keycodes_0.0.9.hjson
@@ -0,0 +1,8 @@
+{
+ "ranges": {
+ "0x74C0/0x003F": "!delete!", // Old QK_STENO
+ "0x74C0/0x005F": {
+ "define": "QK_STENO"
+ }
+ }
+}
diff --git a/data/constants/keycodes/keycodes_0.0.9_steno.hjson b/data/constants/keycodes/keycodes_0.0.9_steno.hjson
new file mode 100644
index 00000000000..3742da52e7d
--- /dev/null
+++ b/data/constants/keycodes/keycodes_0.0.9_steno.hjson
@@ -0,0 +1,609 @@
+{
+ "keycodes": {
+ "!reset!":0,
+
+ "0x74C0": {
+ "group": "steno",
+ "key": "QK_STENO_FUNCTION",
+ "aliases": [
+ "ST_FN"
+ ]
+ },
+ "0x74C1": {
+ "group": "steno",
+ "key": "QK_STENO_N1",
+ "aliases": [
+ "ST_N1",
+ "ST_NUM"
+ ]
+ },
+ "0x74C2": {
+ "group": "steno",
+ "key": "QK_STENO_N2",
+ "aliases": [
+ "ST_N2"
+ ]
+ },
+ "0x74C3": {
+ "group": "steno",
+ "key": "QK_STENO_N3",
+ "aliases": [
+ "ST_N3"
+ ]
+ },
+ "0x74C4": {
+ "group": "steno",
+ "key": "QK_STENO_N4",
+ "aliases": [
+ "ST_N4"
+ ]
+ },
+ "0x74C5": {
+ "group": "steno",
+ "key": "QK_STENO_N5",
+ "aliases": [
+ "ST_N5"
+ ]
+ },
+ "0x74C6": {
+ "group": "steno",
+ "key": "QK_STENO_N6",
+ "aliases": [
+ "ST_N6"
+ ]
+ },
+ "0x74C7": {
+ "group": "steno",
+ "key": "QK_STENO_S1",
+ "aliases": [
+ "ST_S1",
+ "ST_SL"
+ ]
+ },
+ "0x74C8": {
+ "group": "steno",
+ "key": "QK_STENO_S2",
+ "aliases": [
+ "ST_S2"
+ ]
+ },
+ "0x74C9": {
+ "group": "steno",
+ "key": "QK_STENO_TL",
+ "aliases": [
+ "ST_TL"
+ ]
+ },
+ "0x74CA": {
+ "group": "steno",
+ "key": "QK_STENO_KL",
+ "aliases": [
+ "ST_KL"
+ ]
+ },
+ "0x74CB": {
+ "group": "steno",
+ "key": "QK_STENO_PL",
+ "aliases": [
+ "ST_PL"
+ ]
+ },
+ "0x74CC": {
+ "group": "steno",
+ "key": "QK_STENO_WL",
+ "aliases": [
+ "ST_WL"
+ ]
+ },
+ "0x74CD": {
+ "group": "steno",
+ "key": "QK_STENO_HL",
+ "aliases": [
+ "ST_HL"
+ ]
+ },
+ "0x74CE": {
+ "group": "steno",
+ "key": "QK_STENO_RL",
+ "aliases": [
+ "ST_RL"
+ ]
+ },
+ "0x74CF": {
+ "group": "steno",
+ "key": "QK_STENO_A",
+ "aliases": [
+ "ST_A"
+ ]
+ },
+ "0x74D0": {
+ "group": "steno",
+ "key": "QK_STENO_O",
+ "aliases": [
+ "ST_O"
+ ]
+ },
+ "0x74D1": {
+ "group": "steno",
+ "key": "QK_STENO_ST1",
+ "aliases": [
+ "ST_ST1",
+ "ST_STR"
+ ]
+ },
+ "0x74D2": {
+ "group": "steno",
+ "key": "QK_STENO_ST2",
+ "aliases": [
+ "ST_ST2"
+ ]
+ },
+ "0x74D3": {
+ "group": "steno",
+ "key": "QK_STENO_RESET1",
+ "aliases": [
+ "ST_RE1",
+ "ST_RES1"
+ ]
+ },
+ "0x74D4": {
+ "group": "steno",
+ "key": "QK_STENO_RESET2",
+ "aliases": [
+ "ST_RE2",
+ "ST_RES2"
+ ]
+ },
+ "0x74D5": {
+ "group": "steno",
+ "key": "QK_STENO_POWER",
+ "aliases": [
+ "ST_PWR"
+ ]
+ },
+ "0x74D6": {
+ "group": "steno",
+ "key": "QK_STENO_ST3",
+ "aliases": [
+ "ST_ST3"
+ ]
+ },
+ "0x74D7": {
+ "group": "steno",
+ "key": "QK_STENO_ST4",
+ "aliases": [
+ "ST_ST4"
+ ]
+ },
+ "0x74D8": {
+ "group": "steno",
+ "key": "QK_STENO_E",
+ "aliases": [
+ "ST_E"
+ ]
+ },
+ "0x74D9": {
+ "group": "steno",
+ "key": "QK_STENO_U",
+ "aliases": [
+ "ST_U"
+ ]
+ },
+ "0x74DA": {
+ "group": "steno",
+ "key": "QK_STENO_FR",
+ "aliases": [
+ "ST_FR"
+ ]
+ },
+ "0x74DB": {
+ "group": "steno",
+ "key": "QK_STENO_RR",
+ "aliases": [
+ "ST_RR"
+ ]
+ },
+ "0x74DC": {
+ "group": "steno",
+ "key": "QK_STENO_PR",
+ "aliases": [
+ "ST_PR"
+ ]
+ },
+ "0x74DD": {
+ "group": "steno",
+ "key": "QK_STENO_BR",
+ "aliases": [
+ "ST_BR"
+ ]
+ },
+ "0x74DE": {
+ "group": "steno",
+ "key": "QK_STENO_LR",
+ "aliases": [
+ "ST_LR"
+ ]
+ },
+ "0x74DF": {
+ "group": "steno",
+ "key": "QK_STENO_GR",
+ "aliases": [
+ "ST_GR"
+ ]
+ },
+ "0x74E0": {
+ "group": "steno",
+ "key": "QK_STENO_TR",
+ "aliases": [
+ "ST_TR"
+ ]
+ },
+ "0x74E1": {
+ "group": "steno",
+ "key": "QK_STENO_SR",
+ "aliases": [
+ "ST_SR"
+ ]
+ },
+ "0x74E2": {
+ "group": "steno",
+ "key": "QK_STENO_DR",
+ "aliases": [
+ "ST_DR"
+ ]
+ },
+ "0x74E3": {
+ "group": "steno",
+ "key": "QK_STENO_N7",
+ "aliases": [
+ "ST_N7"
+ ]
+ },
+ "0x74E4": {
+ "group": "steno",
+ "key": "QK_STENO_N8",
+ "aliases": [
+ "ST_N8"
+ ]
+ },
+ "0x74E5": {
+ "group": "steno",
+ "key": "QK_STENO_N9",
+ "aliases": [
+ "ST_N9"
+ ]
+ },
+ "0x74E6": {
+ "group": "steno",
+ "key": "QK_STENO_NA",
+ "aliases": [
+ "ST_NA"
+ ]
+ },
+ "0x74E7": {
+ "group": "steno",
+ "key": "QK_STENO_NB",
+ "aliases": [
+ "ST_NB"
+ ]
+ },
+ "0x74E8": {
+ "group": "steno",
+ "key": "QK_STENO_NC",
+ "aliases": [
+ "ST_NC"
+ ]
+ },
+ "0x74E9": {
+ "group": "steno",
+ "key": "QK_STENO_ZR",
+ "aliases": [
+ "ST_ZR"
+ ]
+ },
+ "0x74EA": {
+ "group": "steno",
+ "key": "QK_STENO_X1",
+ "aliases": [
+ "ST_X1"
+ ]
+ },
+ "0x74EB": {
+ "group": "steno",
+ "key": "QK_STENO_X2",
+ "aliases": [
+ "ST_X2"
+ ]
+ },
+ "0x74EC": {
+ "group": "steno",
+ "key": "QK_STENO_X3",
+ "aliases": [
+ "ST_X3"
+ ]
+ },
+ "0x74ED": {
+ "group": "steno",
+ "key": "QK_STENO_X4",
+ "aliases": [
+ "ST_X4"
+ ]
+ },
+ "0x74EE": {
+ "group": "steno",
+ "key": "QK_STENO_X5",
+ "aliases": [
+ "ST_X5"
+ ]
+ },
+ "0x74EF": {
+ "group": "steno",
+ "key": "QK_STENO_X6",
+ "aliases": [
+ "ST_X6"
+ ]
+ },
+ "0x74F0": {
+ "group": "steno",
+ "key": "QK_STENO_X7",
+ "aliases": [
+ "ST_X7"
+ ]
+ },
+ "0x74F1": {
+ "group": "steno",
+ "key": "QK_STENO_X8",
+ "aliases": [
+ "ST_X8"
+ ]
+ },
+ "0x74F2": {
+ "group": "steno",
+ "key": "QK_STENO_X9",
+ "aliases": [
+ "ST_X9"
+ ]
+ },
+ "0x74F3": {
+ "group": "steno",
+ "key": "QK_STENO_X10",
+ "aliases": [
+ "ST_X10"
+ ]
+ },
+ "0x74F4": {
+ "group": "steno",
+ "key": "QK_STENO_X11",
+ "aliases": [
+ "ST_X11"
+ ]
+ },
+ "0x74F5": {
+ "group": "steno",
+ "key": "QK_STENO_X12",
+ "aliases": [
+ "ST_X12"
+ ]
+ },
+ "0x74F6": {
+ "group": "steno",
+ "key": "QK_STENO_X13",
+ "aliases": [
+ "ST_X13"
+ ]
+ },
+ "0x74F7": {
+ "group": "steno",
+ "key": "QK_STENO_X14",
+ "aliases": [
+ "ST_X14"
+ ]
+ },
+ "0x74F8": {
+ "group": "steno",
+ "key": "QK_STENO_X15",
+ "aliases": [
+ "ST_X15"
+ ]
+ },
+ "0x74F9": {
+ "group": "steno",
+ "key": "QK_STENO_X16",
+ "aliases": [
+ "ST_X16"
+ ]
+ },
+ "0x74FA": {
+ "group": "steno",
+ "key": "QK_STENO_X17",
+ "aliases": [
+ "ST_X17"
+ ]
+ },
+ "0x74FB": {
+ "group": "steno",
+ "key": "QK_STENO_X18",
+ "aliases": [
+ "ST_X18"
+ ]
+ },
+ "0x74FC": {
+ "group": "steno",
+ "key": "QK_STENO_X19",
+ "aliases": [
+ "ST_X19"
+ ]
+ },
+ "0x74FD": {
+ "group": "steno",
+ "key": "QK_STENO_X20",
+ "aliases": [
+ "ST_X20"
+ ]
+ },
+ "0x74FE": {
+ "group": "steno",
+ "key": "QK_STENO_X21",
+ "aliases": [
+ "ST_X21"
+ ]
+ },
+ "0x74FF": {
+ "group": "steno",
+ "key": "QK_STENO_X22",
+ "aliases": [
+ "ST_X22"
+ ]
+ },
+ "0x7500": {
+ "group": "steno",
+ "key": "QK_STENO_X23",
+ "aliases": [
+ "ST_X23"
+ ]
+ },
+ "0x7501": {
+ "group": "steno",
+ "key": "QK_STENO_X24",
+ "aliases": [
+ "ST_X24"
+ ]
+ },
+ "0x7502": {
+ "group": "steno",
+ "key": "QK_STENO_X25",
+ "aliases": [
+ "ST_X25"
+ ]
+ },
+ "0x7503": {
+ "group": "steno",
+ "key": "QK_STENO_X26",
+ "aliases": [
+ "ST_X26"
+ ]
+ },
+ // 0x7504
+ // 0x7505
+ // 0x7506
+ // 0x7507
+ // 0x7508
+ // 0x7509
+ // 0x750A
+ "0x750B": {
+ "group": "steno",
+ "key": "QK_STENO_S3",
+ "aliases": [
+ "ST_S3"
+ ]
+ },
+ "0x750C": {
+ "group": "steno",
+ "key": "QK_STENO_TKL",
+ "aliases": [
+ "ST_TKL"
+ ]
+ },
+ "0x750D": {
+ "group": "steno",
+ "key": "QK_STENO_PWL",
+ "aliases": [
+ "ST_PWL"
+ ]
+ },
+ "0x750E": {
+ "group": "steno",
+ "key": "QK_STENO_HRL",
+ "aliases": [
+ "ST_HRL"
+ ]
+ },
+ "0x750F": {
+ "group": "steno",
+ "key": "QK_STENO_FRR",
+ "aliases": [
+ "ST_FRR"
+ ]
+ },
+ "0x7510": {
+ "group": "steno",
+ "key": "QK_STENO_PBR",
+ "aliases": [
+ "ST_PBR"
+ ]
+ },
+ "0x7511": {
+ "group": "steno",
+ "key": "QK_STENO_LGR",
+ "aliases": [
+ "ST_LGR"
+ ]
+ },
+ "0x7512": {
+ "group": "steno",
+ "key": "QK_STENO_TSR",
+ "aliases": [
+ "ST_TSR"
+ ]
+ },
+ "0x7513": {
+ "group": "steno",
+ "key": "QK_STENO_DZR",
+ "aliases": [
+ "ST_DZR"
+ ]
+ },
+ "0x7514": {
+ "group": "steno",
+ "key": "QK_STENO_AO",
+ "aliases": [
+ "ST_AO"
+ ]
+ },
+ "0x7515": {
+ "group": "steno",
+ "key": "QK_STENO_EU",
+ "aliases": [
+ "ST_EU"
+ ]
+ },
+ // 0x7516
+ // 0x7517
+ // 0x7518
+ // 0x7519
+ // 0x751A
+ // 0x751B
+ "0x751C": {
+ "group": "steno",
+ "key": "QK_STENO_MODE_BOLT",
+ "label": "Steno Mode TX Bolt",
+ "aliases": [
+ "ST_BOLT"
+ ]
+ },
+ "0x751D": {
+ "group": "steno",
+ "key": "QK_STENO_MODE_GEMINI",
+ "label": "Steno Mode GeminiPR",
+ "aliases": [
+ "ST_GEMI"
+ ]
+ },
+ "0x751E": {
+ "group": "steno",
+ "key": "QK_STENO_MODE_NEXT",
+ "label": "Steno Mode Next",
+ "aliases": [
+ "ST_NEXT"
+ ]
+ },
+ "0x751F": {
+ "group": "steno",
+ "key": "QK_STENO_MODE_PREVIOUS",
+ "label": "Steno Mode Previous",
+ "aliases": [
+ "ST_PREV"
+ ]
+ }
+ }
+}
diff --git a/data/constants/module_hooks/1.1.3.hjson b/data/constants/module_hooks/1.1.3.hjson
new file mode 100644
index 00000000000..61764a0af66
--- /dev/null
+++ b/data/constants/module_hooks/1.1.3.hjson
@@ -0,0 +1,3 @@
+{
+ // This version exists to signify addition of eeconfig support.
+}
diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson
index e86932e9ddf..f8cbd28d708 100644
--- a/data/mappings/info_config.hjson
+++ b/data/mappings/info_config.hjson
@@ -217,6 +217,9 @@
"SPLIT_ST7565_ENABLE": {"info_key": "split.transport.sync.st7565", "value_type": "flag"},
"SPLIT_WPM_ENABLE": {"info_key": "split.transport.sync.wpm", "value_type": "flag"},
+ // Stenography
+ "STENO_COMBINEDMAP": {"info_key": "stenography.combined_map", "value_type": "flag"},
+
// Tapping
"CHORDAL_HOLD": {"info_key": "tapping.chordal_hold", "value_type": "flag"},
"FLOW_TAP_TERM": {"info_key": "tapping.flow_tap_term", "value_type": "int"},
diff --git a/data/mappings/keyboard_aliases.hjson b/data/mappings/keyboard_aliases.hjson
index 71a7e880a3d..60cb7270428 100644
--- a/data/mappings/keyboard_aliases.hjson
+++ b/data/mappings/keyboard_aliases.hjson
@@ -1741,7 +1741,10 @@
"target": "ducky/one2mini/1861st"
},
"ducky/one2sf": {
- "target": "ducky/one2sf/1967st"
+ "target": "ducky/one2sf/1967st/ansi"
+ },
+ "ducky/one2sf/1967st": {
+ "target": "ducky/one2sf/1967st/ansi"
},
"dumbpad": {
"target": "dumbpad/v0x"
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index ef2b4802a40..1e28d176574 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -815,6 +815,17 @@
"additionalProperties": false,
"properties": {
"enabled": {"type": "boolean"},
+ "combined_map": {"type": "boolean"},
+ "default": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mode": {
+ "type": "string",
+ "enum": ["geminipr", "txbolt"]
+ }
+ }
+ },
"protocol": {
"type": "string",
"enum": ["all", "geminipr", "txbolt"]
diff --git a/docs/ChangeLog/20260830.md b/docs/ChangeLog/20260830.md
new file mode 100644
index 00000000000..757dc3f0f92
--- /dev/null
+++ b/docs/ChangeLog/20260830.md
@@ -0,0 +1,189 @@
+# QMK Breaking Changes - 2026 August 30 Changelog
+
+## Notable Changes {#notable-changes}
+
+### Community Modules `1.1.3` ([#26201](https://github.com/qmk/qmk_firmware/pull/26201)) {#community-modules}
+
+Version 1.1.3 adds support for persistent data in community modules. Modules can now store and restore their own state across restarts, enabling more stateful behavior without relying on keyboard-level EEPROM handling. A reference example can be located at [modules/qmk/nvm_test](https://github.com/qmk/qmk_firmware/tree/develop/modules/qmk/nvm_test).
+
+See the [Community Modules documentation](../features/community_modules) for more information, including the full list of available hooks.
+
+### Steno Feature Updates ([#26273](https://github.com/qmk/qmk_firmware/pull/26273), [#26018](https://github.com/qmk/qmk_firmware/pull/26018)) {#steno}
+
+The steno feature has been reworked around a clearer integration, including a more consistent keycode naming scheme.
+Users should migrate old `STN_*` and legacy mode names to the new `QK_STENO_*`/`ST_*` naming scheme.
+
+::: warning
+Keycode aliases have been put in place in most cases to cater for "old names" being mapped to "new names" -- the documentation already reflects all the new naming of keys.
+:::
+
+
+ Full list of updated keycodes
+
+| Old Keycode | New Keycode | Aliases |
+|----------------------|------------------------|--------------------|
+| `STN_FN` | `QK_STENO_FUNCTION` | `ST_FN` |
+| `STN_N1`/`STN_NUM` | `QK_STENO_N1` | `ST_N1`/`ST_NUM` |
+| `STN_N2` | `QK_STENO_N2` | `ST_N2` |
+| `STN_N3` | `QK_STENO_N3` | `ST_N3` |
+| `STN_N4` | `QK_STENO_N4` | `ST_N4` |
+| `STN_N5` | `QK_STENO_N5` | `ST_N5` |
+| `STN_N6` | `QK_STENO_N6` | `ST_N6` |
+| `STN_S1`/`STN_SL` | `QK_STENO_S1` | `ST_S1`/`ST_SL` |
+| `STN_S2` | `QK_STENO_S2` | `ST_S2` |
+| `STN_TL` | `QK_STENO_TL` | `ST_TL` |
+| `STN_KL` | `QK_STENO_KL` | `ST_KL` |
+| `STN_PL` | `QK_STENO_PL` | `ST_PL` |
+| `STN_WL` | `QK_STENO_WL` | `ST_WL` |
+| `STN_HL` | `QK_STENO_HL` | `ST_HL` |
+| `STN_RL` | `QK_STENO_RL` | `ST_RL` |
+| `STN_A` | `QK_STENO_A` | `ST_A` |
+| `STN_O` | `QK_STENO_O` | `ST_O` |
+| `STN_ST1`/`STN_STR` | `QK_STENO_ST1` | `ST_ST1`/`ST_STR` |
+| `STN_ST2` | `QK_STENO_ST2` | `ST_ST2` |
+| `STN_RE1`/`STN_RES1` | `QK_STENO_RESET1` | `ST_RES1`/`ST_RE1` |
+| `STN_RE2`/`STN_RES2` | `QK_STENO_RESET2` | `ST_RES2`/`ST_RE2` |
+| `STN_PWR` | `QK_STENO_POWER` | `ST_PWR` |
+| `STN_ST3` | `QK_STENO_ST3` | `ST_ST3` |
+| `STN_ST4` | `QK_STENO_ST4` | `ST_ST4` |
+| `STN_E` | `QK_STENO_E` | `ST_E` |
+| `STN_U` | `QK_STENO_U` | `ST_U` |
+| `STN_FR` | `QK_STENO_FR` | `ST_FR` |
+| `STN_RR` | `QK_STENO_RR` | `ST_RR` |
+| `STN_PR` | `QK_STENO_PR` | `ST_PR` |
+| `STN_BR` | `QK_STENO_BR` | `ST_BR` |
+| `STN_LR` | `QK_STENO_LR` | `ST_LR` |
+| `STN_GR` | `QK_STENO_GR` | `ST_GR` |
+| `STN_TR` | `QK_STENO_TR` | `ST_TR` |
+| `STN_SR` | `QK_STENO_SR` | `ST_SR` |
+| `STN_DR` | `QK_STENO_DR` | `ST_DR` |
+| `STN_N7` | `QK_STENO_N7` | `ST_N7` |
+| `STN_N8` | `QK_STENO_N8` | `ST_N8` |
+| `STN_N9` | `QK_STENO_N9` | `ST_N9` |
+| `STN_NA` | `QK_STENO_NA` | `ST_NA` |
+| `STN_NB` | `QK_STENO_NB` | `ST_NB` |
+| `STN_NC` | `QK_STENO_NC` | `ST_NC` |
+| `STN_ZR` | `QK_STENO_ZR` | `ST_ZR` |
+| `STN_SL` | `QK_STENO_S1` | `ST_S1` |
+| `STN_STR` | `QK_STENO_ST1` | `ST_ST1` |
+| `STN_S3` | `QK_STENO_S3` | `ST_S3` |
+| `STN_TKL` | `QK_STENO_TKL` | `ST_TKL` |
+| `STN_PWL` | `QK_STENO_PWL` | `ST_PWL` |
+| `STN_HRL` | `QK_STENO_HRL` | `ST_HRL` |
+| `STN_FRR` | `QK_STENO_FRR` | `ST_FRR` |
+| `STN_PBR` | `QK_STENO_PBR` | `ST_PBR` |
+| `STN_LGR` | `QK_STENO_LGR` | `ST_LGR` |
+| `STN_TSR` | `QK_STENO_TSR` | `ST_TSR` |
+| `STN_DZR` | `QK_STENO_DZR` | `ST_DZR` |
+| `STN_AO` | `QK_STENO_AO` | `ST_AO` |
+| `STN_EU` | `QK_STENO_EU` | `ST_EU` |
+| `QK_STENO_BOLT` | `QK_STENO_MODE_BOLT` | `ST_BOLT` |
+| `QK_STENO_GEMINI` | `QK_STENO_MODE_GEMINI` | `ST_GEMI` |
+
+
+
+Support for the [Plover custom HID protocol](https://github.com/opensteno/plover/releases/tag/v5.1.0) has also been integrated. This provides an alternative to the COM port based Gemini and Bolt protocols, and extends steno support to VUSB based devices.
+
+::: info Note
+A tighter integration of the Plover HID protocol into the steno feature is planned for a future release.
+:::
+
+See the [Stenography Feature](../features/stenography) documentation for more information.
+
+### Remove pin ordering restriction in RP2040 ps2 driver ([#26256](https://github.com/qmk/qmk_firmware/pull/26256)) {#rp2040-ps2}
+
+The RP2040 PS/2 driver no longer requires a strict clock/data pin ordering. This removes an unnecessary wiring restriction for RP2040-based keyboards and allows more valid PS/2 layouts to work without needing to match a specific pin sequence.
+
+### Restrict the EXTRAKEY_ENABLE System Control HID usage range. ([#26295](https://github.com/qmk/qmk_firmware/pull/26295)) {#extrakey-gamepad}
+
+QMK now limits the default System Control HID range exposed by `EXTRAKEY_ENABLE` to the safe subset it actually uses. This prevents issues where some hosts to misidentify the device as a gamepad.
+
+To widen the range to the old behavior, the following can be added to a `config.h`:
+
+```c
+#define SYSTEM_CONTROL_USAGE_MINIMUM 0x0001
+#define SYSTEM_CONTROL_USAGE_MAXIMUM 0x00B7
+```
+
+::: warning
+Only widen it if you need the extra usages and know your host handles them.
+:::
+
+### Updated Keyboard Codebases {#updated-keyboard-codebases}
+
+| Old Keyboard Name | New Keyboard Name |
+|---------------------|--------------------------|
+| ducky/one2sf/1967st | ducky/one2sf/1967st/ansi |
+
+## Deprecation Notices
+
+In line with the [notice period](../support_deprecation_policy#how-much-advance-notice-will-be-given), deprecation notices for larger items are listed here.
+
+### VIA Feature Migration ([#26315](https://github.com/qmk/qmk_firmware/pull/26315)) {#via-module}
+
+As part of long-term goal to progressively reduce the maintenance burden on the project, upkeep of the VIA integration will transition to the VIA team.
+
+This allows the VIA team to support many more custom keyboard configurations, as well as reduces the turnaround time for any changes to the VIA protocol they wish to make.
+
+Backwards compatibility will remain for a transition period and in a future release, the old VIA feature-based implementation is expected to be removed.
+
+## Full changelist
+
+Core:
+* Custom plover HID report type ([#26018](https://github.com/qmk/qmk_firmware/pull/26018))
+* Enable modules to persist data ([#26201](https://github.com/qmk/qmk_firmware/pull/26201))
+* Preserve Azoteq mouse buttons ([#26248](https://github.com/qmk/qmk_firmware/pull/26248))
+* Remove pin ordering restriction in RP2040 ps2 driver ([#26256](https://github.com/qmk/qmk_firmware/pull/26256))
+* Plover HID cleanup. ([#26262](https://github.com/qmk/qmk_firmware/pull/26262))
+* repeat_key.c: add implementation for get_last_record ([#26263](https://github.com/qmk/qmk_firmware/pull/26263))
+* Implement Plover HID for VUSB ([#26267](https://github.com/qmk/qmk_firmware/pull/26267))
+* process_key_lock: clear entire key state in cancel_key_lock() ([#26269](https://github.com/qmk/qmk_firmware/pull/26269))
+* Initial rework of steno feature ([#26273](https://github.com/qmk/qmk_firmware/pull/26273))
+* qp_lvgl: always signal flush ready even with no display ([#26275](https://github.com/qmk/qmk_firmware/pull/26275))
+* Consistently handle datablock init ([#26282](https://github.com/qmk/qmk_firmware/pull/26282))
+* Make framebuffer effects honour `rgb_matrix_map_row_column_to_led` ([#26294](https://github.com/qmk/qmk_firmware/pull/26294))
+* Restrict the EXTRAKEY_ENABLE System Control HID usage range. ([#26295](https://github.com/qmk/qmk_firmware/pull/26295))
+* Port typing_heatmap animation to LED Matrix ([#26300](https://github.com/qmk/qmk_firmware/pull/26300))
+* Add `_noeeprom` variants of backlight enable/disable. ([#26328](https://github.com/qmk/qmk_firmware/pull/26328))
+* Add STM32_USB_USE_OTG2 to USB_ENDPOINTS_ARE_REORDERABLE ([#26369](https://github.com/qmk/qmk_firmware/pull/26369))
+* Change preprocessor directive for random solenoid firing ([#26377](https://github.com/qmk/qmk_firmware/pull/26377))
+* Rework Plover HID to use Steno keycodes ([#26421](https://github.com/qmk/qmk_firmware/pull/26421))
+
+CLI:
+* Require `--keyboard` for some CLI subcommands ([#26308](https://github.com/qmk/qmk_firmware/pull/26308))
+* Be lazier in loading keyboard schema for new-keyboard ([#26340](https://github.com/qmk/qmk_firmware/pull/26340))
+
+Keyboards:
+* Addition of the Ymdk Oni Tsangan/HHKB-like pcb ([#25230](https://github.com/qmk/qmk_firmware/pull/25230))
+* Add converter/thinkpad_t6x/pico_t61 keyboard ([#26266](https://github.com/qmk/qmk_firmware/pull/26266))
+* Add additional layouts for `mkh_studio/bully` ([#26271](https://github.com/qmk/qmk_firmware/pull/26271))
+* Split `ducky/one2sf/1967st` into `ansi`/`iso` variants ([#26277](https://github.com/qmk/qmk_firmware/pull/26277))
+* Automatically handle duplicate matrix LED mappings ([#26278](https://github.com/qmk/qmk_firmware/pull/26278))
+* Tidy sawnsprojects/satxri6key ([#26317](https://github.com/qmk/qmk_firmware/pull/26317))
+* Update satisfaction75 to only use keyboard datablock ([#26320](https://github.com/qmk/qmk_firmware/pull/26320))
+* Migrate remaining `VIA_EEPROM_CUSTOM_CONFIG_SIZE` to `EECONFIG_KB_DATA_SIZE` ([#26321](https://github.com/qmk/qmk_firmware/pull/26321))
+* Use core `spi_init` implementation for gmmk/gmmk2/p96 ([#26344](https://github.com/qmk/qmk_firmware/pull/26344))
+* Convert `novelkeys/nk87` to use RGB Matrix ([#26349](https://github.com/qmk/qmk_firmware/pull/26349))
+* Update magic_force/mf17 to WS2812 PWM driver ([#26384](https://github.com/qmk/qmk_firmware/pull/26384))
+* Keycult TKL Updates ([#26385](https://github.com/qmk/qmk_firmware/pull/26385))
+* Update keyboards to implement `led_update_kb` instead of `led_set` ([#26388](https://github.com/qmk/qmk_firmware/pull/26388))
+
+Keyboard fixes:
+* Fix nifty_numpad issues ([#26283](https://github.com/qmk/qmk_firmware/pull/26283))
+* Fix use of `via.h` ([#26316](https://github.com/qmk/qmk_firmware/pull/26316))
+
+Others:
+* Update RGB Matrix documentation to include JSON config ([#26187](https://github.com/qmk/qmk_firmware/pull/26187))
+* Update encoder documents for json config ([#26188](https://github.com/qmk/qmk_firmware/pull/26188))
+* Update LED Matrix documentation to include JSON config ([#26425](https://github.com/qmk/qmk_firmware/pull/26425))
+
+Bugs:
+* First pass of ruff check fixes ([#26257](https://github.com/qmk/qmk_firmware/pull/26257))
+* Use `memmove` for overlapping copies in RGB/LED matrix last-hit tracker ([#26306](https://github.com/qmk/qmk_firmware/pull/26306))
+* Fix to make Repeat Key QK_REP work with Key Overrides. ([#26312](https://github.com/qmk/qmk_firmware/pull/26312))
+* Fix SEQUENCER_ENABLE so the sequencer feature builds again ([#26322](https://github.com/qmk/qmk_firmware/pull/26322))
+* Fix ChibiOS virtual serial short packet receive ([#26356](https://github.com/qmk/qmk_firmware/pull/26356))
+* Resolve recursive keyboard aliases when locating userspace keymaps ([#26402](https://github.com/qmk/qmk_firmware/pull/26402))
+* Fix `EECONFIG_MODULE_DATA_SIZE` for modules with zero provisioned eeconfig ([#26414](https://github.com/qmk/qmk_firmware/pull/26414))
+* Align USB endpoint buffers to fix RP2040 Plover HID issues ([#26417](https://github.com/qmk/qmk_firmware/pull/26417))
+* Fix 'qmk generate-develop-pr-list' for ghapi v2 ([#26428](https://github.com/qmk/qmk_firmware/pull/26428))
diff --git a/docs/_sidebar.json b/docs/_sidebar.json
index 357574fe7e9..894287c16d0 100644
--- a/docs/_sidebar.json
+++ b/docs/_sidebar.json
@@ -214,7 +214,7 @@
{ "text": "My Pull Request Was Flagged", "link": "/breaking_changes_instructions" },
{
"text": "Most Recent ChangeLog",
- "link": "/ChangeLog/20260531"
+ "link": "/ChangeLog/20260830"
},
{ "text": "Past Breaking Changes", "link": "/breaking_changes_history" },
{ "text": "Deprecation Policy", "link": "/support_deprecation_policy" }
diff --git a/docs/breaking_changes.md b/docs/breaking_changes.md
index 3b169498b87..66d9d404486 100644
--- a/docs/breaking_changes.md
+++ b/docs/breaking_changes.md
@@ -10,25 +10,25 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
## What has been included in past Breaking Changes?
+* [2026 Aug 30](ChangeLog/20260830)
* [2026 May 31](ChangeLog/20260531)
* [2026 Feb 22](ChangeLog/20260222)
-* [2025 Nov 30](ChangeLog/20251130)
* [Older Breaking Changes](breaking_changes_history)
## When is the next Breaking Change?
-The next Breaking Change is scheduled for Aug 30, 2026.
+The next Breaking Change is scheduled for November 29, 2026.
### Important Dates
-* 2025 May 31 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
-* 2026 Aug 2 - `develop` closed to new PRs.
-* 2026 Aug 2 - Call for testers.
-* 2026 Aug 16 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
-* 2026 Aug 23 - `develop` is locked, only critical bugfix PRs merged.
-* 2026 Aug 28 - `master` is locked, no PRs merged.
-* 2026 Aug 30 - Merge `develop` to `master`.
-* 2026 Aug 30 - `master` is unlocked. PRs can be merged again.
+* 2025 Aug 30 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
+* 2026 Nov 1 - `develop` closed to new PRs.
+* 2026 Nov 1 - Call for testers.
+* 2026 Nov 15 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
+* 2026 Nov 22 - `develop` is locked, only critical bugfix PRs merged.
+* 2026 Nov 27 - `master` is locked, no PRs merged.
+* 2026 Nov 29 - Merge `develop` to `master`.
+* 2026 Nov 29 - `master` is unlocked. PRs can be merged again.
## What changes will be included?
diff --git a/docs/breaking_changes_history.md b/docs/breaking_changes_history.md
index f313ea63286..7edee445de4 100644
--- a/docs/breaking_changes_history.md
+++ b/docs/breaking_changes_history.md
@@ -2,6 +2,7 @@
This page links to all previous changelogs from the QMK Breaking Changes process.
+* [2026 Aug 30](ChangeLog/20260830) - version 0.34.0
* [2026 May 31](ChangeLog/20260531) - version 0.33.0
* [2026 Feb 22](ChangeLog/20260222) - version 0.32.0
* [2025 Nov 30](ChangeLog/20251130) - version 0.31.0
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index 02f362b14c8..1c532de7c4d 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -214,7 +214,7 @@ options:
-p PRINT, --print PRINT
For each matched target, print the value of the supplied info.json key. May be passed multiple times.
-f FILTER, --filter FILTER
- Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight=true'. Valid functions are 'absent', 'contains', 'exists' and 'length'. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'.
+ Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight==true'. Valid functions are 'absent', 'contains', 'exists' and 'length'. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'.
```
## `qmk console`
diff --git a/docs/config_options.md b/docs/config_options.md
index 95cc89eaa7e..fa18b4c7d16 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -340,6 +340,10 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_TRANSACTION_IDS_USER .....`
* Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](features/split_keyboard#custom-data-sync) for more information.
+* `#define SYSTEM_CONTROL_USAGE_MINIMUM 0x0081`
+* `#define SYSTEM_CONTROL_USAGE_MAXIMUM 0x008F`
+ * Sets the usage range reported by the System Control collection that `EXTRAKEY_ENABLE` adds. The default range covers the System Control usages QMK can send and stops below the Generic Desktop D-pad usages (`0x90` and up). Raising the maximum into that range makes some hosts detect the keyboard as a gamepad, so only widen it if you need the extra usages and know your host handles them. The minimum must not be greater than the maximum.
+
# The `rules.mk` File
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
diff --git a/docs/feature_eeprom.md b/docs/feature_eeprom.md
index 5cdd6d99818..c11ad2445b0 100644
--- a/docs/feature_eeprom.md
+++ b/docs/feature_eeprom.md
@@ -191,7 +191,9 @@ void eeconfig_init_user_datablock(void);
:::::
-### Example
+### Examples
+
+#### Basic
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here.
@@ -215,10 +217,6 @@ typedef struct my_config_t {
static my_config_t config;
void keyboard_post_init_user(void) {
- if (!eeconfig_is_user_datablock_valid()) {
- eeconfig_init_user_datablock();
- }
-
eeconfig_read_user_datablock(&config, 0, sizeof(my_config_t));
}
@@ -240,3 +238,20 @@ void housekeeping_task_user(void) {
}
}
```
+
+#### Default Values
+
+Extending the above example, a default value for the datablock can be configured as follows:
+
+```c
+void eeconfig_init_user_datablock(void) {
+ my_config_t default_config = {
+ .data = 42,
+ };
+ eeconfig_update_user_datablock(&default_config, 0, sizeof(my_config_t));
+}
+```
+
+::: tip
+For large datablocks, you might need to manually update in chunks to avoid memory issues.
+:::
diff --git a/docs/features/community_modules.md b/docs/features/community_modules.md
index 2b0086134bd..d38ee79460f 100644
--- a/docs/features/community_modules.md
+++ b/docs/features/community_modules.md
@@ -135,28 +135,45 @@ This file defines LED matrix effects in the same form as used with `led_matrix_k
This file defines RGB matrix effects in the same form as used with `rgb_matrix_kb.inc` and `rgb_matrix_user.inc` (see [Custom RGB Matrix Effects](rgb_matrix#custom-rgb-matrix-effects)). Effect mode names are prepended with `RGB_MATRIX_COMMUNITY_MODULE_`.
-### Custom split keyboard data sync
+### Additional Customization
-Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_` (see [Custom data sync](split_keyboard#custom-data-sync)).
+#### Split Keyboard Data Sync
+
+Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_` (see [Custom data sync](split_keyboard#custom-data-sync)).
+
+#### Persistent Configuration
+
+Defines follow the convention, `EECONFIG_MODULE__DATA_SIZE` and `EECONFIG_MODULE__DATA_VERSION` (see [Custom Persistent Configuration](../feature_eeprom#datablock)).
+
+When configured, the following APIs are available:
+
+| API Format | Example (`hello_world` module) | API Version |
+|--------------------------------------------|-----------------------------------------------|-------------|
+| `eeconfig_is__datablock_valid` | `eeconfig_is_hello_world_datablock_valid` | `1.1.3` |
+| `eeconfig_read__datablock` | `eeconfig_read_hello_world_datablock` | `1.1.3` |
+| `eeconfig_update__datablock` | `eeconfig_update_hello_world_datablock` | `1.1.3` |
+| `eeconfig_init__datablock` | `eeconfig_init_hello_world_datablock` | `1.1.3` |
+| `eeconfig_read__datablock_field` | `eeconfig_read_hello_world_datablock_field` | `1.1.3` |
+| `eeconfig_update__datablock_field` | `eeconfig_update_hello_world_datablock_field` | `1.1.3` |
### Compatible APIs
Community Modules may provide specializations for the following APIs:
-| Base API | API Format | Example (`hello_world` module) | API Version |
-|----------------------------------|-------------------------------------------|---------------------------------------------|-------------|
-| `keyboard_pre_init` | `keyboard_pre_init_` | `keyboard_pre_init_hello_world` | `0.1.0` |
-| `keyboard_post_init` | `keyboard_post_init_` | `keyboard_post_init_hello_world` | `0.1.0` |
-| `pre_process_record` | `pre_process_record_` | `pre_process_record_hello_world` | `0.1.0` |
-| `process_record` | `process_record_` | `process_record_hello_world` | `0.1.0` |
-| `post_process_record` | `post_process_record_` | `post_process_record_hello_world` | `0.1.0` |
-| `housekeeping_task` | `housekeeping_task_` | `housekeeping_task_hello_world` | `1.0.0` |
-| `suspend_power_down` | `suspend_power_down_` | `suspend_power_down_hello_world` | `1.0.0` |
-| `suspend_wakeup_init` | `suspend_wakeup_init_` | `suspend_wakeup_init_hello_world` | `1.0.0` |
-| `shutdown` | `shutdown_` | `shutdown_hello_world` | `1.0.0` |
-| `process_detected_host_os` | `process_detected_host_os_` | `process_detected_host_os_hello_world` | `1.0.0` |
-| `default_layer_state_set` | `default_layer_state_set_` | `default_layer_state_set_hello_world` | `1.1.0` |
-| `layer_state_set` | `layer_state_set_` | `layer_state_set_hello_world` | `1.1.0` |
+| Base API | API Format | Example (`hello_world` module) | API Version |
+|----------------------------------|-------------------------------------------|----------------------------------------------|-------------|
+| `keyboard_pre_init` | `keyboard_pre_init_` | `keyboard_pre_init_hello_world` | `0.1.0` |
+| `keyboard_post_init` | `keyboard_post_init_` | `keyboard_post_init_hello_world` | `0.1.0` |
+| `pre_process_record` | `pre_process_record_` | `pre_process_record_hello_world` | `0.1.0` |
+| `process_record` | `process_record_` | `process_record_hello_world` | `0.1.0` |
+| `post_process_record` | `post_process_record_` | `post_process_record_hello_world` | `0.1.0` |
+| `housekeeping_task` | `housekeeping_task_` | `housekeeping_task_hello_world` | `1.0.0` |
+| `suspend_power_down` | `suspend_power_down_` | `suspend_power_down_hello_world` | `1.0.0` |
+| `suspend_wakeup_init` | `suspend_wakeup_init_` | `suspend_wakeup_init_hello_world` | `1.0.0` |
+| `shutdown` | `shutdown_` | `shutdown_hello_world` | `1.0.0` |
+| `process_detected_host_os` | `process_detected_host_os_` | `process_detected_host_os_hello_world` | `1.0.0` |
+| `default_layer_state_set` | `default_layer_state_set_` | `default_layer_state_set_hello_world` | `1.1.0` |
+| `layer_state_set` | `layer_state_set_` | `layer_state_set_hello_world` | `1.1.0` |
| `led_matrix_indicators` | `led_matrix_indicators_` | `led_matrix_indicators_hello_world` | `1.1.0` |
| `led_matrix_indicators_advanced` | `led_matrix_indicators_advanced_` | `led_matrix_indicators_advanced_hello_world` | `1.1.0` |
| `rgb_matrix_indicators` | `rgb_matrix_indicators_` | `rgb_matrix_indicators_hello_world` | `1.1.0` |
@@ -164,7 +181,6 @@ Community Modules may provide specializations for the following APIs:
| `pointing_device_init` | `pointing_device_init_` | `pointing_device_init_hello_world` | `1.1.0` |
| `pointing_device_task` | `pointing_device_task_` | `pointing_device_task_hello_world` | `1.1.0` |
-
::: info
An unspecified API is disregarded if a Community Module does not provide a specialization for it.
:::
diff --git a/docs/features/encoders.md b/docs/features/encoders.md
index 59f949be65c..45a92f3c77b 100644
--- a/docs/features/encoders.md
+++ b/docs/features/encoders.md
@@ -1,5 +1,25 @@
# Encoders
+:::::tabs
+
+==== JSON
+
+Basic (EC11 compatible) encoders are supported by adding this to your keyboard's json config:
+
+```json
+ "features": {
+ "encoder": true
+ },
+ "encoder": {
+ "rotary": [
+ {"pin_a": "B5", "pin_b": "B6"},
+ {"pin_a": "B7", "pin_b": "B8", "resolution": 2}
+ ]
+ }
+```
+
+==== Legacy
+
Basic (EC11 compatible) encoders are supported by adding this to your `rules.mk`:
```make
@@ -20,11 +40,6 @@ Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.
#define ENCODER_B_PINS { encoder1b, encoder2b }
```
-If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define:
-
-```c
-#define ENCODER_DIRECTION_FLIP
-```
Additionally, the resolution, which defines how many pulses the encoder registers between each detent, can be defined with:
@@ -38,6 +53,14 @@ It can also be defined per-encoder, by instead defining:
#define ENCODER_RESOLUTIONS { 4, 2 }
```
+:::::
+
+If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define:
+
+```c
+#define ENCODER_DIRECTION_FLIP
+```
+
For 4× encoders you also can assign default position if encoder skips pulses when it changes direction. For example, if your encoder send high level on both pins by default, define this:
```c
@@ -46,6 +69,50 @@ For 4× encoders you also can assign default position if encoder skips pulses wh
## Split Keyboards
+:::::tabs
+
+==== JSON
+
+If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
+
+```json
+ "encoder": {
+ "rotary": [
+ {"pin_a": "B4", "pin_b": "B3"}
+ ]
+ },
+ "split": {
+ "encoder": {
+ "right": {
+ "rotary": [
+ {"pin_a": "D4", "pin_b": "D2", "resolution": 2}
+ ]
+ }
+ }
+ }
+```
+
+If the `"right"` definitions are not specified, then the non-right version will be applied to both sides of the split.
+
+Additionally, if one side does not have an encoder, you can specify no encoder for the pins/resolution -- for example, a split keyboard with only a right-side encoder:
+
+```json
+ "encoder": {
+ "rotary": []
+ },
+ "split": {
+ "encoder": {
+ "right": {
+ "rotary": [
+ {"pin_a": "D4", "pin_b": "D2", "resolution": 2}
+ ]
+ }
+ }
+ }
+```
+
+==== Legacy
+
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
```c
@@ -66,6 +133,7 @@ Additionally, if one side does not have an encoder, you can specify `{}` for the
#define ENCODER_B_PINS_RIGHT { B13 }
#define ENCODER_RESOLUTIONS_RIGHT { 4 }
```
+:::::
::: warning
Keep in mind that whenever you change the encoder resolution, you will need to reflash the half that has the encoder affected by the change.
@@ -73,11 +141,26 @@ Keep in mind that whenever you change the encoder resolution, you will need to r
## Encoder map {#encoder-map}
-Encoder mapping may be added to your `keymap.c`, which replicates the normal keyswitch layer handling functionality, but with encoders. Add this to your keymap's `rules.mk`:
+Encoder mapping may be added to your `keymap.c`, which replicates the normal keyswitch layer handling functionality, but with encoders. Add this to your keymap's config:
+
+:::::tabs
+
+==== keymap.json
+
+```json
+ "config": {
+ "features": {
+ "encoder_map": true
+ }
+ }
+```
+
+==== rules.mk
```make
ENCODER_MAP_ENABLE = yes
```
+:::::
Your `keymap.c` will then need an encoder mapping defined (for four layers and two encoders):
@@ -103,7 +186,7 @@ Using encoder mapping pumps events through the normal QMK keycode processing pip
```
::: tip
-By default, the encoder map delay matches the value of `TAP_CODE_DELAY`.
+By default, the encoder map delay matches the value of `qmk.tap_keycode_delay` (or `TAP_CODE_DELAY`).
:::
## Callbacks
@@ -172,15 +255,47 @@ Multiple encoders may share pins so long as each encoder has a distinct pair of
- pads must be high at the detent stability point which is called 'default position' in QMK
- no more than two encoders sharing a pin can be turned at the same time
-For example you can support two encoders using only 3 pins like this
+For example you can support two encoders using only 3 pins like this:
+:::::tabs
+==== JSON
+
+```json
+ "encoder": {
+ "rotary": [
+ {"pin_a": "B1", "pin_b": "B2"},
+ {"pin_a": "B1", "pin_b": "B3"}
+ ]
+ }
```
+
+==== Legacy
+
+```c
#define ENCODER_A_PINS { B1, B1 }
#define ENCODER_B_PINS { B2, B3 }
```
+:::::
+
You could even support three encoders using only three pins (one per encoder) however in this configuration, rotating two encoders which share pins simultaneously will often generate incorrect output. For example:
+:::::tabs
+
+==== JSON
+```json
+ "encoder": {
+ "rotary": [
+ {"pin_a": "B1", "pin_b": "B2"},
+ {"pin_a": "B1", "pin_b": "B3"},
+ {"pin_a": "B2", "pin_b": "B3"}
+ ]
+ }
```
+
+==== Legacy
+
+```c
#define ENCODER_A_PINS { B1, B1, B2 }
#define ENCODER_B_PINS { B2, B3, B3 }
```
+:::::
Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case
diff --git a/docs/features/led_matrix.md b/docs/features/led_matrix.md
index f14fb47d62d..c45af14b22a 100644
--- a/docs/features/led_matrix.md
+++ b/docs/features/led_matrix.md
@@ -24,16 +24,64 @@ LED Matrix is an abstraction layer on top of an underlying LED driver API. The l
|[IS31FL3746A](../drivers/is31fl3746a)|72 |
|[SNLED27351](../drivers/snled27351) |192 |
-To assign the LED Matrix driver, add the following to your `rules.mk`, for example:
+To assign the LED Matrix driver, add the following to your keyboard config, for example:
+
+:::::tabs
+
+==== `JSON`
+
+```json
+ "led_matrix": {
+ "driver": "is31fl3218"
+ }
+```
+
+==== `rules.mk`
```make
LED_MATRIX_DRIVER = is31fl3218
```
+:::::
+
## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:
+:::::tabs
+
+==== `JSON`
+
+```json
+ "led_matrix": {
+ "layout": [
+ {"matrix": [0, 3], "x": 188, "y": 16, "flags": 1},
+ {"matrix": [1, 3], "x": 187, "y": 48, "flags": 4},
+ {"matrix": [2, 3], "x": 147, "y": 64, "flags": 4},
+ {"matrix": [2, 0], "x": 112, "y": 64, "flags": 4},
+ {"matrix": [1, 0], "x": 37, "y": 48, "flags": 4},
+ {"matrix": [0, 0], "x": 38, "y": 16, "flags": 1}
+ ]
+ }
+```
+
+The first part, `matrix`, tells the system what key this LED represents using the key's electrical matrix row & col. This part is optional, if the LED doesn't correspond to a switch (such as underglow leds).
+
+The second and third parts represents the LED's physical `x, y` position on the keyboard. The default expected range of values for `x` is `0-224`, and the default expected range of values for `y` is `0-64`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position:
+
+```c
+x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
+y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
+```
+
+Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
+
+As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `led_matrix.center_point = [ 112, 32 ]` in their json with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
+
+The last value `flags` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
+
+==== `.c`
+
```c
led_config_t g_led_config = { {
// Key Matrix to LED Index
@@ -63,6 +111,8 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{
`// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
+:::::
+
## Flags {#flags}
|Define |Value |Description |
@@ -119,12 +169,75 @@ enum led_matrix_effects {
LED_MATRIX_SOLID_MULTISPLASH, // Value pulses away from multiple key hits then fades out
LED_MATRIX_WAVE_LEFT_RIGHT, // Sine wave scrolling from left to right
LED_MATRIX_WAVE_UP_DOWN, // Sine wave scrolling from up to down
+ LED_MATRIX_TYPING_HEATMAP, // How hot is your WPM!
LED_MATRIX_EFFECT_MAX
};
```
-You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
+:::::tabs
+==== `JSON`
+
+You can enable a single effect by setting it true in the `led_matrix.animations` section in your json:
+
+```json
+ "led_matrix": {
+ "animations": {
+ "alphas_mods": true,
+ "breathing": true,
+ "band": true,
+ "band_pinwheel": true,
+ "band_spiral": true,
+ "cycle_left_right": true,
+ "cycle_up_down": true,
+ "cycle_out_in": true,
+ "dual_beacon": true,
+ "wave_left_right": true,
+ "wave_up_down": true,
+ }
+ },
+```
+
+**Framebuffer effects**
+
+```json
+ "led_matrix": {
+ "animations": {
+ "typing_heatmap": true,
+ }
+ }
+```
+
+::: tip
+These modes introduce additional logic that can increase firmware size.
+:::
+
+**Reactive effects**
+
+```json
+ "led_matrix": {
+ "animations": {
+ "solid_reactive_simple": true,
+ "solid_reactive": true,
+ "solid_reactive_wide": true,
+ "solid_reactive_multiwide": true,
+ "solid_reactive_cross": true,
+ "solid_reactive_multicross": true,
+ "solid_reactive_nexus": true,
+ "solid_reactive_multinexus": true,
+ "splash": true,
+ "multisplash": true,
+ }
+ }
+```
+
+::: tip
+These modes introduce additional logic that can increase firmware size.
+:::
+
+==== `config.h`
+
+You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
|Define |Description |
|-------------------------------------------------------|----------------------------------------------|
@@ -140,6 +253,14 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT` |Enables `LED_MATRIX_WAVE_LEFT_RIGHT` |
|`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` |
+|Framebuffer Defines |Description |
+|------------------------------------------------------|-----------------------------------------------|
+|`#define ENABLE_LED_MATRIX_TYPING_HEATMAP` |Enables `LED_MATRIX_TYPING_HEATMAP` |
+
+::: tip
+These modes introduce additional logic that can increase firmware size.
+:::
+
|Reactive Defines |Description |
|-------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
@@ -156,6 +277,44 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
These modes introduce additional logic that can increase firmware size.
:::
+:::::
+
+### LED Matrix Effect Typing Heatmap {#led-matrix-effect-typing-heatmap}
+
+This effect will scale the LED matrix brightness according to a heatmap of recently pressed keys. Whenever a key is pressed its "temperature" increases as well as that of its neighboring keys. The temperature of each key is then decreased automatically every 25 milliseconds by default.
+
+In order to change the delay of temperature decrease define `LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS`:
+
+```c
+#define LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 50
+```
+
+As heatmap uses the physical position of the leds set in the g_led_config, you may need to tweak the following options to get the best effect for your keyboard. Note the size of this grid is `224x64`.
+
+Limit the distance the effect spreads to surrounding keys.
+
+```c
+#define LED_MATRIX_TYPING_HEATMAP_SPREAD 40
+```
+
+Limit how hot surrounding keys get from each press.
+
+```c
+#define LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
+```
+
+Remove the spread effect entirely.
+
+```c
+#define LED_MATRIX_TYPING_HEATMAP_SLIM
+```
+
+It's also possible to adjust the tempo of *heating up*. It's defined as the number of steps by which to increment the brightness. Decreasing this value increases the number of keystrokes needed to fully heat up the key.
+
+```c
+#define LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP 32
+```
+
## Custom LED Matrix Effects {#custom-led-matrix-effects}
By setting `LED_MATRIX_CUSTOM_USER = yes` in `rules.mk`, new effects can be defined directly from your keymap or userspace, without having to edit any QMK core files. To declare new effects, create a `led_matrix_user.inc` file in the user keymap directory or userspace folder.
@@ -235,11 +394,61 @@ const char* effect_name = led_matrix_get_mode_name(led_matrix_get_mode());
`led_matrix_get_mode_name()` is not enabled by default as it increases the amount of flash memory used by the firmware based on the number of effects enabled.
:::
-
-## Additional `config.h` Options {#additional-configh-options}
+## Additional Configuration Options {#additional-configh-options}
```c
#define LED_MATRIX_MODE_NAME_ENABLE // enables led_matrix_get_mode_name()
+```
+
+:::::tabs
+
+==== `JSON`
+
+```json
+ "led_matrix": {
+ "default": {
+ // Sets the default enabled state, if none has been set
+ "on": true,
+ // Sets the default mode, if none has been set
+ "animation": "solid",
+ // Sets the default brightness value, if none has been set
+ "val": 127,
+ // Sets the default speed, if none has been set
+ "speed": 127,
+ // Sets the default flag, if none has been set
+ "flags": 255
+ },
+ // Sets the flags which can be cycled through
+ "flag_steps": [
+ // LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_NONE
+ 255, 5, 0
+ ],
+ // limits max brightness of leds
+ "max_brightness": 255,
+ // number of milliseconds to wait until led automatically turns off
+ "timeout": 0,
+ // The value by which to increment the brightness per adjustment action
+ "val_steps": 16,
+ // The value by which to increment the animation speed per adjustment action
+ "speed_steps": 16,
+ // limits in milliseconds how frequently an animation will update the LEDs.
+ // 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
+ "led_flush_limit": 16,
+ // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
+ "led_process_limit": 15,
+ // reactive effects respond to keyreleases (instead of keypresses)
+ "react_on_keyup": true,
+ // turn off effects when suspended
+ "sleep": true,
+ // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
+ // If reactive effects are enabled, you also will want to enable split.transport.sync.matrix_state
+ "split_count": [X, Y],
+ }
+```
+
+==== `config.h`
+
+```c
#define LED_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define LED_MATRIX_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off
#define LED_MATRIX_SLEEP // turn off effects when suspended
@@ -258,6 +467,8 @@ const char* effect_name = led_matrix_get_mode_name(led_matrix_get_mode());
#define LED_MATRIX_FLAG_STEPS { LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_NONE } // Sets the flags which can be cycled through.
```
+:::::
+
## EEPROM storage {#eeprom-storage}
The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time).
diff --git a/docs/features/ps2_mouse.md b/docs/features/ps2_mouse.md
index 6ef7e467682..9f875d9b816 100644
--- a/docs/features/ps2_mouse.md
+++ b/docs/features/ps2_mouse.md
@@ -166,7 +166,7 @@ In your keyboard config.h:
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU.
-There are strict requirements for pin ordering but any pair of GPIO pins can be used. The GPIO used for clock must be directly after data, see the included info.json snippet for an example of correct order.
+The GPIOs used for clock and data must be consecutive (in either order).
You may optionally switch the PIO peripheral used with the following define in config.h:
```c
diff --git a/docs/features/rgb_matrix.md b/docs/features/rgb_matrix.md
index 36680f24a26..32840b595ff 100644
--- a/docs/features/rgb_matrix.md
+++ b/docs/features/rgb_matrix.md
@@ -27,16 +27,64 @@ RGB Matrix is an abstraction layer on top of an underlying LED driver API. The l
|[SNLED27351](../drivers/snled27351) |64 |
|[WS2812](../drivers/ws2812) |? |
-To assign the RGB Matrix driver, add the following to your `rules.mk`, for example:
+To assign the RGB Matrix driver, add the following to your keyboard config, for example:
+
+:::::tabs
+
+==== `JSON`
+
+```json
+ "rgb_matrix": {
+ "driver": "is31fl3218"
+ }
+```
+
+==== `rules.mk`
```make
RGB_MATRIX_DRIVER = is31fl3218
```
+:::::
+
## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:
+:::::tabs
+
+==== `JSON`
+
+```json
+ "rgb_matrix": {
+ "layout": [
+ {"matrix": [0, 3], "x": 188, "y": 16, "flags": 1},
+ {"matrix": [1, 3], "x": 187, "y": 48, "flags": 4},
+ {"matrix": [2, 3], "x": 147, "y": 64, "flags": 4},
+ {"matrix": [2, 0], "x": 112, "y": 64, "flags": 4},
+ {"matrix": [1, 0], "x": 37, "y": 48, "flags": 4},
+ {"matrix": [0, 0], "x": 38, "y": 16, "flags": 1}
+ ]
+ }
+```
+
+The first part, `matrix`, tells the system what key this LED represents using the key's electrical matrix row & col. This part is optional, if the LED doesn't correspond to a switch (such as underglow leds).
+
+The second and third parts represents the LED's physical `x, y` position on the keyboard. The default expected range of values for `x` is `0-224`, and the default expected range of values for `y` is `0-64`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position:
+
+```c
+x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
+y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
+```
+
+Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
+
+As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `rgb_matrix.center_point = [ 112, 32 ]` in their json with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
+
+The last value `flags` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
+
+==== `.c`
+
```c
led_config_t g_led_config = { {
// Key Matrix to LED Index
@@ -62,10 +110,12 @@ y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
-As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `#define RGB_MATRIX_CENTER { 112, 32 }` in their config.h file with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `{ x, y }` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
+As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `rgb_matrix.center_point = [ 112, 32]` in their json (or `#define RGB_MATRIX_CENTER {112, 32}` in their config.h file) with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
`// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
+:::::
+
## Flags {#flags}
|Define |Value |Description |
@@ -160,8 +210,113 @@ enum rgb_matrix_effects {
};
```
-You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
+:::::tabs
+==== `JSON`
+
+You can enable a single effect by setting it true in the `rgb_matrix.animations` section in your json:
+
+```json
+ "rgb_matrix": {
+ "animations": {
+ "alphas_mods": true,
+ "gradient_up_down": true,
+ "gradient_left_right": true,
+ "breathing": true,
+ "band_sat": true,
+ "band_val": true,
+ "band_pinwheel_sat": true,
+ "band_pinwheel_val": true,
+ "band_spiral_sat": true,
+ "band_spiral_val": true,
+ "cycle_all": true,
+ "cycle_left_right": true,
+ "cycle_up_down": true,
+ "rainbow_moving_chevron": true,
+ "cycle_out_in": true,
+ "cycle_out_in_dual": true,
+ "cycle_pinwheel": true,
+ "cycle_spiral": true,
+ "dual_beacon": true,
+ "rainbow_beacon": true,
+ "rainbow_pinwheels": true,
+ "raindrops": true,
+ "jellybean_raindrops": true,
+ "hue_breathing": true,
+ "hue_pendulum": true,
+ "hue_wave": true,
+ "pixel_rain": true,
+ "pixel_flow": true,
+ "pixel_fractal": true,
+ "typing_heatmap": true,
+ "digital_rain": true,
+ "solid_reactive_simple": true,
+ "solid_reactive": true,
+ "solid_reactive_wide": true,
+ "solid_reactive_multiwide": true,
+ "solid_reactive_cross": true,
+ "solid_reactive_multicross": true,
+ "solid_reactive_nexus": true,
+ "solid_reactive_multinexus": true,
+ "splash": true,
+ "multispash": true,
+ "solid_splash": true,
+ "solid_multisplash": true,
+ "starlight": true,
+ "starlight_smooth": true,
+ "starlight_dual_hue": true,
+ "starlight_dual_sat": true,
+ "riverflow": true
+
+ }
+ },
+```
+
+**Framebuffer effects**
+
+```json
+ "rgb_matrix": {
+ "animations": {
+ "typing_heatmap": true,
+ "digital_rain": true,
+ }
+ }
+```
+
+::: tip
+These modes introduce additional logic that can increase firmware size.
+:::
+
+**Reactive effects**
+
+```json
+ "rgb_matrix": {
+ "animations": {
+ "solid_reactive_simple": true,
+ "solid_reactive": true,
+ "solid_reactive_wide": true,
+ "solid_reactive_multiwide": true,
+ "solid_reactive_cross": true,
+ "solid_reactive_multicross": true,
+ "solid_reactive_nexus": true,
+ "solid_reactive_multinexus": true,
+ "splash": true,
+ "multisplash": true,
+ "solid_splash": true,
+ "solid_multisplash": true
+ }
+ }
+```
+
+
+::: tip
+These modes introduce additional logic that can increase firmware size.
+:::
+
+
+==== `config.h`
+
+You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
|Define |Description |
|------------------------------------------------------|----------------------------------------------|
@@ -229,6 +384,7 @@ These modes introduce additional logic that can increase firmware size.
These modes introduce additional logic that can increase firmware size.
:::
+:::::
### RGB Matrix Effect Typing Heatmap {#rgb-matrix-effect-typing-heatmap}
@@ -387,10 +543,69 @@ const char* effect_name = rgb_matrix_get_mode_name(rgb_matrix_get_mode());
:::
-## Additional `config.h` Options {#additional-configh-options}
+## Additional Configuration Options {#additional-configh-options}
```c
#define RGB_MATRIX_MODE_NAME_ENABLE // enables rgb_matrix_get_mode_name()
+```
+
+:::::tabs
+
+==== `JSON`
+
+```json
+ "rgb_matrix": {
+ "default": {
+ // Sets the default enabled state, if none has been set
+ "on": true,
+ // Sets the default mode, if none has been set
+ "animation": "cycle_left_right",
+ // Sets the default hue value, if none has been set
+ "hue": 0,
+ // Sets the default saturation value, if none has been set
+ "sat": 255,
+ // Sets the default brightness value, if none has been set
+ "val": 127,
+ // Sets the default speed, if none has been set
+ "speed": 127,
+ // Sets the default flag, if none has been set
+ "flags": 255
+ },
+ // Sets the flags which can be cycled through
+ "flag_steps": [
+ // LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_UNDERGLOW, LED_FLAG_NONE
+ 255, 5, 2, 0
+ ],
+ // limits max brightness of leds
+ "max_brightness": 255,
+ // number of milliseconds to wait until rgb automatically turns off
+ "timeout": 0,
+ // The value by which to increment the hue per adjustment action
+ "hue_steps": 8,
+ // The value by which to increment the saturation per adjustment action
+ "sat_steps": 16,
+ // The value by which to increment the brightness per adjustment action
+ "val_steps": 16,
+ // The value by which to increment the animation speed per adjustment action
+ "speed_steps": 16,
+ // limits in milliseconds how frequently an animation will update the LEDs.
+ // 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
+ "led_flush_limit": 16,
+ // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
+ "led_process_limit": 15,
+ // reactive effects respond to keyreleases (instead of keypresses)
+ "react_on_keyup": true,
+ // turn off effects when suspended
+ "sleep": true,
+ // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
+ // If reactive effects are enabled, you also will want to enable split.transport.sync.matrix_state
+ "split_count": [X, Y],
+ }
+```
+
+==== `config.h`
+
+```c
#define RGB_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define RGB_MATRIX_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
#define RGB_MATRIX_SLEEP // turn off effects when suspended
@@ -414,6 +629,8 @@ const char* effect_name = rgb_matrix_get_mode_name(rgb_matrix_get_mode());
#define RGB_MATRIX_FLAG_STEPS { LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_UNDERGLOW, LED_FLAG_NONE } // Sets the flags which can be cycled through.
```
+:::::
+
## EEPROM storage {#eeprom-storage}
The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time).
diff --git a/docs/features/stenography.md b/docs/features/stenography.md
index b253890e134..b0cd747043d 100644
--- a/docs/features/stenography.md
+++ b/docs/features/stenography.md
@@ -6,11 +6,12 @@ The [Open Steno Project](https://www.openstenoproject.org/) has built an open-so
## Steno Support in QMK
-There are three ways that QMK keyboards can support steno, with varying degrees of configuration required:
+There are four ways that QMK keyboards can support steno, with varying degrees of configuration required:
1. Plover with [Arpeggiation](https://plover.wiki/index.php/Glossary#Arpeggiate) requires no changes to any keyboard and is supported by QMK as well as any other QWERTY keyboard.
2. Plover with [NKRO](https://plover.wiki/index.php/Using_a_standard_keyboard_with_Plover#NKRO). If your keyboard supports NKRO in hardware and you have NKRO enabled as a USB endpoint, you can chord with the keyboard. Many devices will arrive stock like this and will require no changes.
3. Steno Machine Protocols. This requires the most configuration, but this has the advantage of allowing you to use your keyboard keys normally (either on another layer or another piece of hardware) without enabling and disabling your steno software.
+4. Plover HID Protocol. This is a custom HID protocol that Plover can understand, but does not require a COM port. It is robust to device disconnects and saves an interface over the COM-based alternatives.
## Plover with QWERTY Keyboard {#plover-with-qwerty-keyboard}
@@ -92,9 +93,27 @@ Examples of steno strokes and the associated packet:
- `WAZ` = `10000000 00000010 00100000 00000000 00000000 00000001`
- `PHAPBGS` = `10000000 00000101 00100000 00000000 01101010 00000000`
-### Switching protocols on the fly {#switching-protocols-on-the-fly}
+## Plover HID Protocol {#plover-hid-protocol}
-If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press the `QK_STENO_BOLT` and `QK_STENO_GEMINI` keycodes in order to switch protocols on the fly.
+This mode operates independently of the other Steno "official" machine protocols. Like any other mouse or keyboard, it uses the USB HID protocol to communicate with Plover by sending an 8 byte (64 bit) packet representing a bitfield for all the possible keys on a steno machine plus a number of additional general purpose keys for custom use. This protocol is only understood by Plover as of [5.1.0](https://github.com/opensteno/plover/releases/tag/v5.1.0).
+
+To enable this functionality, add the following lines to your `rules.mk`:
+
+```make
+PLOVER_HID_ENABLE = yes
+```
+
+::: warning
+The Plover HID Protocol is currently mutually exclusive with the other steno protocols and will be disabled when `STENO_ENABLE` is set.
+:::
+
+All of the possible keycodes are defined with the `ST_` prefix and are available without any additional includes.
+
+More details can be found here: https://github.com/dnaq/plover-machine-hid
+
+## Switching protocols on the fly {#switching-protocols-on-the-fly}
+
+If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press one of the [mode keycodes](#keycode-reference-mode) in order to switch protocols on the fly.
To enable these special keycodes, add the following lines to your `rules.mk`:
```make
@@ -106,6 +125,13 @@ If you want to switch protocols programmatically, as part of a custom macro for
The default protocol is Gemini PR but the last protocol used is stored in non-volatile memory so QMK will remember your choice between reboots of your keyboard — assuming that your keyboard features (emulated) EEPROM.
+To configure the default, add one of the following lines to your `config.h`:
+
+```c
+#define STENO_DEFAULT_MODE STENO_MODE_GEMINI
+#define STENO_DEFAULT_MODE STENO_MODE_BOLT
+```
+
Naturally, this option takes the most amount of firmware space as it needs to compile the code for all the available stenography protocols. In most cases, compiling a single stenography protocol is sufficient.
The default value for `STENO_PROTOCOL` is `all`.
@@ -126,7 +152,7 @@ To test your keymap, you can chord keys on your keyboard and either look at the
## Learning Stenography {#learning-stenography}
-* [Learn Plover!](https://sites.google.com/site/learnplover/)
+* [Learn Plover!](https://opensteno.org/learn-plover/)
* [Steno Jig](https://joshuagrams.github.io/steno-jig/)
* More resources at the Plover [Learning Stenography](https://github.com/openstenoproject/plover/wiki/Learning-Stenography) wiki
@@ -144,7 +170,7 @@ This function is called when a chord is about to be sent. Mode will be one of `S
bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
```
-This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_BOLT`, `QK_STENO_GEMINI`, or one of the `STN_*` key values.
+This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_MODE_BOLT`, `QK_STENO_MODE_GEMINI`, or one of the `ST_*` key values.
```c
bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys);
@@ -154,7 +180,7 @@ This function is called after a key has been processed, but before any decision
If `record->event.pressed` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
-The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[STN_E, STN_U, STN_BR, STN_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice.
+The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[ST_E, ST_U, ST_BR, ST_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice.
The `n_pressed_keys` argument is the number of physical keys actually being held down.
This is not always equal to the number of bits set to 1 (aka the [Hamming weight](https://en.wikipedia.org/wiki/Hamming_weight)) in `chord` because it is possible to simultaneously press down four keys, then release three of those four keys and then press yet another key while the fourth finger is still holding down its key.
@@ -163,67 +189,117 @@ At the end of this scenario given as an example, `chord` would have five bits se
## Keycode Reference {#keycode-reference}
+### Mode {#keycode-reference-mode}
+
+When more than one protocol is enabled, the following keycodes are available:
+
+| Key | Aliases | Description |
+|---------------------------|---------|---------------------------------------------------------------------------|
+|`QK_STENO_MODE_BOLT` |`ST_BOLT`| Set mode to `STENO_MODE_BOLT` (when multiple protocols are enabled) |
+|`QK_STENO_MODE_GEMINI` |`ST_GEMI`| Set mode to `STENO_MODE_GEMINI` (when multiple protocols are enabled) |
+|`QK_STENO_MODE_NEXT` |`ST_NEXT`| Cycle through modes (when multiple protocols are enabled) |
+|`QK_STENO_MODE_PREVIOUS` |`ST_PREV`| Cycle through modes in reverse (when multiple protocols are enabled) |
+
+### General {#keycode-reference-general}
+
::: info
TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
:::
-|GeminiPR|TX Bolt|Steno Key|
-|--------|-------|-----------|
-|`STN_N1`|`STN_NUM`|Number bar #1|
-|`STN_N2`|`STN_NUM`|Number bar #2|
-|`STN_N3`|`STN_NUM`|Number bar #3|
-|`STN_N4`|`STN_NUM`|Number bar #4|
-|`STN_N5`|`STN_NUM`|Number bar #5|
-|`STN_N6`|`STN_NUM`|Number bar #6|
-|`STN_N7`|`STN_NUM`|Number bar #7|
-|`STN_N8`|`STN_NUM`|Number bar #8|
-|`STN_N9`|`STN_NUM`|Number bar #9|
-|`STN_NA`|`STN_NUM`|Number bar #A|
-|`STN_NB`|`STN_NUM`|Number bar #B|
-|`STN_NC`|`STN_NUM`|Number bar #C|
-|`STN_S1`|`STN_SL`| `S-` upper|
-|`STN_S2`|`STN_SL`| `S-` lower|
-|`STN_TL`|`STN_TL`| `T-`|
-|`STN_KL`|`STN_KL`| `K-`|
-|`STN_PL`|`STN_PL`| `P-`|
-|`STN_WL`|`STN_WL`| `W-`|
-|`STN_HL`|`STN_HL`| `H-`|
-|`STN_RL`|`STN_RL`| `R-`|
-|`STN_A`|`STN_A`| `A` vowel|
-|`STN_O`|`STN_O`| `O` vowel|
-|`STN_ST1`|`STN_STR`| `*` upper-left |
-|`STN_ST2`|`STN_STR`| `*` lower-left|
-|`STN_ST3`|`STN_STR`| `*` upper-right|
-|`STN_ST4`|`STN_STR`| `*` lower-right|
-|`STN_E`|`STN_E`| `E` vowel|
-|`STN_U`|`STN_U`| `U` vowel|
-|`STN_FR`|`STN_FR`| `-F`|
-|`STN_RR`|`STN_RR`| `-R`|
-|`STN_PR`|`STN_PR`| `-P`|
-|`STN_BR`|`STN_BR`| `-B`|
-|`STN_LR`|`STN_LR`| `-L`|
-|`STN_GR`|`STN_GR`| `-G`|
-|`STN_TR`|`STN_TR`| `-T`|
-|`STN_SR`|`STN_SR`| `-S`|
-|`STN_DR`|`STN_DR`| `-D`|
-|`STN_ZR`|`STN_ZR`| `-Z`|
-|`STN_FN`|| (Function)|
-|`STN_RES1`||(Reset 1)|
-|`STN_RES2`||(Reset 2)|
-|`STN_PWR`||(Power)|
+| Key | GeminiPR | TX Bolt | Description |
+|---------------------|-----------|----------|-----------------|
+| `QK_STENO_N1` | `ST_N1` | `ST_NUM` | Number bar #1 |
+| `QK_STENO_N2` | `ST_N2` | `ST_NUM` | Number bar #2 |
+| `QK_STENO_N3` | `ST_N3` | `ST_NUM` | Number bar #3 |
+| `QK_STENO_N4` | `ST_N4` | `ST_NUM` | Number bar #4 |
+| `QK_STENO_N5` | `ST_N5` | `ST_NUM` | Number bar #5 |
+| `QK_STENO_N6` | `ST_N6` | `ST_NUM` | Number bar #6 |
+| `QK_STENO_N7` | `ST_N7` | `ST_NUM` | Number bar #7 |
+| `QK_STENO_N8` | `ST_N8` | `ST_NUM` | Number bar #8 |
+| `QK_STENO_N9` | `ST_N9` | `ST_NUM` | Number bar #9 |
+| `QK_STENO_NA` | `ST_NA` | `ST_NUM` | Number bar #A |
+| `QK_STENO_NB` | `ST_NB` | `ST_NUM` | Number bar #B |
+| `QK_STENO_NC` | `ST_NC` | `ST_NUM` | Number bar #C |
+| `QK_STENO_S1` | `ST_S1` | `ST_SL` | `S-` upper |
+| `QK_STENO_S2` | `ST_S2` | `ST_SL` | `S-` lower |
+| `QK_STENO_TL` | `ST_TL` | `ST_TL` | `T-` |
+| `QK_STENO_KL` | `ST_KL` | `ST_KL` | `K-` |
+| `QK_STENO_PL` | `ST_PL` | `ST_PL` | `P-` |
+| `QK_STENO_WL` | `ST_WL` | `ST_WL` | `W-` |
+| `QK_STENO_HL` | `ST_HL` | `ST_HL` | `H-` |
+| `QK_STENO_RL` | `ST_RL` | `ST_RL` | `R-` |
+| `QK_STENO_A` | `ST_A` | `ST_A` | `A` vowel |
+| `QK_STENO_O` | `ST_O` | `ST_O` | `O` vowel |
+| `QK_STENO_ST1` | `ST_ST1` | `ST_STR` | `*` upper-left |
+| `QK_STENO_ST2` | `ST_ST2` | `ST_STR` | `*` lower-left |
+| `QK_STENO_ST3` | `ST_ST3` | `ST_STR` | `*` upper-right |
+| `QK_STENO_ST4` | `ST_ST4` | `ST_STR` | `*` lower-right |
+| `QK_STENO_E` | `ST_E` | `ST_E` | `E` vowel |
+| `QK_STENO_U` | `ST_U` | `ST_U` | `U` vowel |
+| `QK_STENO_FR` | `ST_FR` | `ST_FR` | `-F` |
+| `QK_STENO_RR` | `ST_RR` | `ST_RR` | `-R` |
+| `QK_STENO_PR` | `ST_PR` | `ST_PR` | `-P` |
+| `QK_STENO_BR` | `ST_BR` | `ST_BR` | `-B` |
+| `QK_STENO_LR` | `ST_LR` | `ST_LR` | `-L` |
+| `QK_STENO_GR` | `ST_GR` | `ST_GR` | `-G` |
+| `QK_STENO_TR` | `ST_TR` | `ST_TR` | `-T` |
+| `QK_STENO_SR` | `ST_SR` | `ST_SR` | `-S` |
+| `QK_STENO_DR` | `ST_DR` | `ST_DR` | `-D` |
+| `QK_STENO_ZR` | `ST_ZR` | `ST_ZR` | `-Z` |
+| `QK_STENO_FUNCTION` | `ST_FN` | | (Function) |
+| `QK_STENO_RESET1` | `ST_RES1` | | (Reset 1) |
+| `QK_STENO_RESET2` | `ST_RES2` | | (Reset 2) |
+| `QK_STENO_POWER` | `ST_PWR` | | (Power) |
+
+### Protocol Specific {#keycode-reference-protocol-specific}
+
+#### Plover HID {#keycode-reference-plover-hid}
+
+Additional keycodes available for the [Plover HID Protocol](#plover-hid-protocol):
+
+| Key | Aliases | Description |
+|----------------|----------|-------------------------------------|
+| `QK_STENO_X1` | `ST_X1` | Extra button 1 (Protocol specific) |
+| `QK_STENO_X2` | `ST_X2` | Extra button 2 (Protocol specific) |
+| `QK_STENO_X3` | `ST_X3` | Extra button 3 (Protocol specific) |
+| `QK_STENO_X4` | `ST_X4` | Extra button 4 (Protocol specific) |
+| `QK_STENO_X5` | `ST_X5` | Extra button 5 (Protocol specific) |
+| `QK_STENO_X6` | `ST_X6` | Extra button 6 (Protocol specific) |
+| `QK_STENO_X7` | `ST_X7` | Extra button 7 (Protocol specific) |
+| `QK_STENO_X8` | `ST_X8` | Extra button 8 (Protocol specific) |
+| `QK_STENO_X9` | `ST_X9` | Extra button 9 (Protocol specific) |
+| `QK_STENO_X10` | `ST_X10` | Extra button 10 (Protocol specific) |
+| `QK_STENO_X11` | `ST_X11` | Extra button 11 (Protocol specific) |
+| `QK_STENO_X12` | `ST_X12` | Extra button 12 (Protocol specific) |
+| `QK_STENO_X13` | `ST_X13` | Extra button 13 (Protocol specific) |
+| `QK_STENO_X14` | `ST_X14` | Extra button 14 (Protocol specific) |
+| `QK_STENO_X15` | `ST_X15` | Extra button 15 (Protocol specific) |
+| `QK_STENO_X16` | `ST_X16` | Extra button 16 (Protocol specific) |
+| `QK_STENO_X17` | `ST_X17` | Extra button 17 (Protocol specific) |
+| `QK_STENO_X18` | `ST_X18` | Extra button 18 (Protocol specific) |
+| `QK_STENO_X19` | `ST_X19` | Extra button 19 (Protocol specific) |
+| `QK_STENO_X20` | `ST_X20` | Extra button 20 (Protocol specific) |
+| `QK_STENO_X21` | `ST_X21` | Extra button 21 (Protocol specific) |
+| `QK_STENO_X22` | `ST_X22` | Extra button 22 (Protocol specific) |
+| `QK_STENO_X23` | `ST_X23` | Extra button 23 (Protocol specific) |
+| `QK_STENO_X24` | `ST_X24` | Extra button 24 (Protocol specific) |
+| `QK_STENO_X25` | `ST_X25` | Extra button 25 (Protocol specific) |
+| `QK_STENO_X26` | `ST_X26` | Extra button 26 (Protocol specific) |
+
+### Combined Map {#keycode-reference-combinedmap}
If you do not want to hit two keys with one finger combined keycodes can be used. These cause both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
-|Combined key | Key1 | Key 2 |
-|---------------|--------|----------|
-|STN_S3 | STN_S1 | STN_S2 |
-|STN_TKL | STN_TL | STN_KL |
-|STN_PWL | STN_PL | STN_WL |
-|STN_HRL | STN_HL | STN_RL |
-|STN_FRR | STN_FR | STN_RR |
-|STN_PBR | STN_PR | STN_BR |
-|STN_LGR | STN_LR | STN_GR |
-|STN_TSR | STN_TR | STN_SR |
-|STN_DZR | STN_DR | STN_ZR |
-|STN_AO | STN_A | STN_O |
-|STN_EU | STN_E | STN_U |
+| Combined key | Aliases | Key 1 | Key 2 |
+|----------------|----------|---------|---------|
+| `QK_STENO_S3` | `ST_S3` | `ST_S1` | `ST_S2` |
+| `QK_STENO_TKL` | `ST_TKL` | `ST_TL` | `ST_KL` |
+| `QK_STENO_PWL` | `ST_PWL` | `ST_PL` | `ST_WL` |
+| `QK_STENO_HRL` | `ST_HRL` | `ST_HL` | `ST_RL` |
+| `QK_STENO_FRR` | `ST_FRR` | `ST_FR` | `ST_RR` |
+| `QK_STENO_PBR` | `ST_PBR` | `ST_PR` | `ST_BR` |
+| `QK_STENO_LGR` | `ST_LGR` | `ST_LR` | `ST_GR` |
+| `QK_STENO_TSR` | `ST_TSR` | `ST_TR` | `ST_SR` |
+| `QK_STENO_DZR` | `ST_DZR` | `ST_DR` | `ST_ZR` |
+| `QK_STENO_AO` | `ST_AO` | `ST_A` | `ST_O` |
+| `QK_STENO_EU` | `ST_EU` | `ST_E` | `ST_U` |
diff --git a/docs/keycodes.md b/docs/keycodes.md
index 9c918b76769..707ba7c9b1d 100644
--- a/docs/keycodes.md
+++ b/docs/keycodes.md
@@ -728,6 +728,96 @@ See also: [Mod-Tap](mod_tap)
|`MEH_T(kc)` | |Left Control, Left Shift and Left Alt when held, `kc` when tapped |
|`HYPR_T(kc)` | |Left Control, Left Shift, Left Alt and Left GUI when held, `kc` when tapped|
+## Stenography {#stenography}
+
+See also: [Stenography](features/stenography)
+
+|Key |Aliases |Description |
+|------------------------|-------------------|---------------------------------------------------------------------|
+|`QK_STENO_FUNCTION` |`ST_FN` |(Function) |
+|`QK_STENO_N1` |`ST_N1`, `ST_NUM` |Number bar #1 |
+|`QK_STENO_N2` |`ST_N2` |Number bar #2 |
+|`QK_STENO_N3` |`ST_N3` |Number bar #3 |
+|`QK_STENO_N4` |`ST_N4` |Number bar #4 |
+|`QK_STENO_N5` |`ST_N5` |Number bar #5 |
+|`QK_STENO_N6` |`ST_N6` |Number bar #6 |
+|`QK_STENO_S1` |`ST_S1`, `ST_SL` |`S-` upper |
+|`QK_STENO_S2` |`ST_S2` |`S-` lower |
+|`QK_STENO_TL` |`ST_TL` |`T-` |
+|`QK_STENO_KL` |`ST_KL` |`K-` |
+|`QK_STENO_PL` |`ST_PL` |`P-` |
+|`QK_STENO_WL` |`ST_WL` |`W-` |
+|`QK_STENO_HL` |`ST_HL` |`H-` |
+|`QK_STENO_RL` |`ST_RL` |`R-` |
+|`QK_STENO_A` |`ST_A` |`A` vowel |
+|`QK_STENO_O` |`ST_O` |`O` vowel |
+|`QK_STENO_ST1` |`ST_ST1`, `ST_STR` |`*` upper-left |
+|`QK_STENO_ST2` |`ST_ST2` |`*` lower-left |
+|`QK_STENO_RESET1` |`ST_RE1`, `ST_RES1`|(Reset 1) |
+|`QK_STENO_RESET2` |`ST_RE2`, `ST_RES2`|(Reset 2) |
+|`QK_STENO_POWER` |`ST_PWR` |(Power) |
+|`QK_STENO_ST3` |`ST_ST3` |`*` upper-right |
+|`QK_STENO_ST4` |`ST_ST4` |`*` lower-right |
+|`QK_STENO_E` |`ST_E` |`E` vowel |
+|`QK_STENO_U` |`ST_U` |`U` vowel |
+|`QK_STENO_FR` |`ST_FR` |`-F` |
+|`QK_STENO_RR` |`ST_RR` |`-R` |
+|`QK_STENO_PR` |`ST_PR` |`-P` |
+|`QK_STENO_BR` |`ST_BR` |`-B` |
+|`QK_STENO_LR` |`ST_LR` |`-L` |
+|`QK_STENO_GR` |`ST_GR` |`-G` |
+|`QK_STENO_TR` |`ST_TR` |`-T` |
+|`QK_STENO_SR` |`ST_SR` |`-S` |
+|`QK_STENO_DR` |`ST_DR` |`-D` |
+|`QK_STENO_N7` |`ST_N7` |Number bar #7 |
+|`QK_STENO_N8` |`ST_N8` |Number bar #8 |
+|`QK_STENO_N9` |`ST_N9` |Number bar #9 |
+|`QK_STENO_NA` |`ST_NA` |Number bar #A |
+|`QK_STENO_NB` |`ST_NB` |Number bar #B |
+|`QK_STENO_NC` |`ST_NC` |Number bar #C |
+|`QK_STENO_ZR` |`ST_ZR` |`-Z` |
+|`QK_STENO_X1` |`ST_X1` |Extra button 1 (Protocol specific) |
+|`QK_STENO_X2` |`ST_X2` |Extra button 2 (Protocol specific) |
+|`QK_STENO_X3` |`ST_X3` |Extra button 3 (Protocol specific) |
+|`QK_STENO_X4` |`ST_X4` |Extra button 4 (Protocol specific) |
+|`QK_STENO_X5` |`ST_X5` |Extra button 5 (Protocol specific) |
+|`QK_STENO_X6` |`ST_X6` |Extra button 6 (Protocol specific) |
+|`QK_STENO_X7` |`ST_X7` |Extra button 7 (Protocol specific) |
+|`QK_STENO_X8` |`ST_X8` |Extra button 8 (Protocol specific) |
+|`QK_STENO_X9` |`ST_X9` |Extra button 9 (Protocol specific) |
+|`QK_STENO_X10` |`ST_X10` |Extra button 10 (Protocol specific) |
+|`QK_STENO_X11` |`ST_X11` |Extra button 11 (Protocol specific) |
+|`QK_STENO_X12` |`ST_X12` |Extra button 12 (Protocol specific) |
+|`QK_STENO_X13` |`ST_X13` |Extra button 13 (Protocol specific) |
+|`QK_STENO_X14` |`ST_X14` |Extra button 14 (Protocol specific) |
+|`QK_STENO_X15` |`ST_X15` |Extra button 15 (Protocol specific) |
+|`QK_STENO_X16` |`ST_X16` |Extra button 16 (Protocol specific) |
+|`QK_STENO_X17` |`ST_X17` |Extra button 17 (Protocol specific) |
+|`QK_STENO_X18` |`ST_X18` |Extra button 18 (Protocol specific) |
+|`QK_STENO_X19` |`ST_X19` |Extra button 19 (Protocol specific) |
+|`QK_STENO_X20` |`ST_X20` |Extra button 20 (Protocol specific) |
+|`QK_STENO_X21` |`ST_X21` |Extra button 21 (Protocol specific) |
+|`QK_STENO_X22` |`ST_X22` |Extra button 22 (Protocol specific) |
+|`QK_STENO_X23` |`ST_X23` |Extra button 23 (Protocol specific) |
+|`QK_STENO_X24` |`ST_X24` |Extra button 24 (Protocol specific) |
+|`QK_STENO_X25` |`ST_X25` |Extra button 25 (Protocol specific) |
+|`QK_STENO_X26` |`ST_X26` |Extra button 26 (Protocol specific) |
+|`QK_STENO_S3` |`ST_S3` |Trigger `ST_S1` and `ST_S2` (when *Combined Map* is enabled) |
+|`QK_STENO_TKL` |`ST_TKL` |Trigger `ST_TL` and `ST_KL` (when *Combined Map* is enabled) |
+|`QK_STENO_PWL` |`ST_PWL` |Trigger `ST_PL` and `ST_WL` (when *Combined Map* is enabled) |
+|`QK_STENO_HRL` |`ST_HRL` |Trigger `ST_HL` and `ST_RL` (when *Combined Map* is enabled) |
+|`QK_STENO_FRR` |`ST_FRR` |Trigger `ST_FR` and `ST_RR` (when *Combined Map* is enabled) |
+|`QK_STENO_PBR` |`ST_PBR` |Trigger `ST_PR` and `ST_BR` (when *Combined Map* is enabled) |
+|`QK_STENO_LGR` |`ST_LGR` |Trigger `ST_LR` and `ST_GR` (when *Combined Map* is enabled) |
+|`QK_STENO_TSR` |`ST_TSR` |Trigger `ST_TR` and `ST_SR` (when *Combined Map* is enabled) |
+|`QK_STENO_DZR` |`ST_DZR` |Trigger `ST_DR` and `ST_ZR` (when *Combined Map* is enabled) |
+|`QK_STENO_AO` |`ST_AO` |Trigger `ST_A` and `ST_O` (when *Combined Map* is enabled) |
+|`QK_STENO_EU` |`ST_EU` |Trigger `ST_E` and `ST_U` (when *Combined Map* is enabled) |
+|`QK_STENO_MODE_BOLT` |`ST_BOLT` |Set mode to `STENO_MODE_BOLT` (when multiple protocols are enabled) |
+|`QK_STENO_MODE_GEMINI` |`ST_GEMI` |Set mode to `STENO_MODE_GEMINI` (when multiple protocols are enabled)|
+|`QK_STENO_MODE_NEXT` |`ST_NEXT` |Cycle through modes (when multiple protocols are enabled) |
+|`QK_STENO_MODE_PREVIOUS`|`ST_PREV` |Cycle through modes in reverse (when multiple protocols are enabled) |
+
## Tapping Term Keys {#tapping-term-keys}
See also: [Dynamic Tapping Term](tap_hold#dynamic-tapping-term)
diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md
index 301e4b12dd0..af7dfff91d1 100644
--- a/docs/reference_info_json.md
+++ b/docs/reference_info_json.md
@@ -866,6 +866,13 @@ Configures the [Stenography](features/stenography) feature.
* `enabled` Boolean
* Enable the Stenography feature.
* Default: `false`
+ * `combined_map` Boolean
+ * Enable the Stenography Combined Map sub-feature.
+ * Default: `false`
+ * `default`
+ * `mode` String
+ * The default mode. Must be one of `geminipr`, `txbolt`.
+ * Default: `"geminipr"` when available, otherwise `"txbolt"`
* `protocol` String
* The Steno protocol to use. Must be one of `all`, `geminipr`, `txbolt`.
* Default: `"all"`
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
index ed2a886854e..d42d6219fbf 100644
--- a/drivers/haptic/solenoid.c
+++ b/drivers/haptic/solenoid.c
@@ -86,7 +86,7 @@ void solenoid_fire(uint8_t index) {
*
*/
void solenoid_fire_handler(void) {
-#ifndef SOLENOID_RANDOM_FIRE
+#ifdef SOLENOID_RANDOM_FIRE
if (NUMBER_OF_SOLENOIDS > 1) {
uint8_t i = rand() % NUMBER_OF_SOLENOIDS;
if (!solenoid_on[i]) {
diff --git a/drivers/sensors/azoteq_iqs5xx.c b/drivers/sensors/azoteq_iqs5xx.c
index 7586ac52d16..02d6d5e01ce 100644
--- a/drivers/sensors/azoteq_iqs5xx.c
+++ b/drivers/sensors/azoteq_iqs5xx.c
@@ -354,7 +354,7 @@ bool azoteq_iqs5xx_init(void) {
};
report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report) {
- report_mouse_t temp_report = {0};
+ report_mouse_t temp_report = {.buttons = mouse_report.buttons};
azoteq_iqs5xx_base_data_t base_data = {0};
i2c_status_t status = azoteq_iqs5xx_get_base_data(&base_data);
diff --git a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.c b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.c
index a410480d7d9..89e1f85862e 100644
--- a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.c
+++ b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.c
@@ -18,6 +18,10 @@
#include "eeprom.h"
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
+#ifdef VIA_ENABLE
+# include "via.h"
+#endif
+
/* Artificial delay added to get media keys to work in the encoder*/
#define MEDIA_KEY_DELAY 10
@@ -54,22 +58,16 @@ void board_init(void) {
}
uint32_t read_custom_config(void *data, uint32_t offset, uint32_t length) {
-#ifdef VIA_ENABLE
- return via_read_custom_config(data, offset, length);
-#else
return eeconfig_read_kb_datablock(data, offset, length);
-#endif
}
uint32_t write_custom_config(const void *data, uint32_t offset, uint32_t length) {
-#ifdef VIA_ENABLE
- return via_update_custom_config(data, offset, length);
-#else
return eeconfig_update_kb_datablock(data, offset, length);
-#endif
}
void keyboard_post_init_kb(void) {
+ custom_config_load();
+
/*
This is a workaround to some really weird behavior
Without this code, the OLED will turn on, but not when you initially plug the keyboard in.
@@ -305,14 +303,8 @@ bool encoder_update_kb(uint8_t index, bool clockwise) {
return true;
}
-void custom_config_reset(void){
- for(int i = 0; i < VIA_EEPROM_CUSTOM_CONFIG_SIZE; ++i) {
- uint8_t dummy = 0;
- write_custom_config(&dummy, i, 1);
- }
-
- uint8_t encoder_modes = 0x1F;
- write_custom_config(&encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
+void custom_config_reset(void) {
+ eeconfig_init_kb_datablock();
}
void custom_config_load(void){
@@ -322,40 +314,20 @@ void custom_config_load(void){
#endif
}
-// Called from via_init() if VIA_ENABLE
-// Called from matrix_init_kb() if not VIA_ENABLE
-void satisfaction_core_init(void)
-{
- // This checks both an EEPROM reset (from bootmagic lite, keycodes)
- // and also firmware build date (from via_eeprom_is_valid())
- if (eeconfig_is_enabled()) {
- custom_config_load();
- } else {
-#ifdef DYNAMIC_KEYMAP_ENABLE
- // Reset the custom stuff
- custom_config_reset();
-#endif
- // DO NOT set EEPROM valid here, let caller do this
- }
+void eeconfig_init_kb_datablock(void) {
+ uint8_t default_data[EECONFIG_KB_DATA_SIZE] = { 0 };
+
+ default_data[EEPROM_ENABLED_ENCODER_MODES_OFFSET] = 0x1F;
+
+ eeconfig_update_kb_datablock(default_data, 0, sizeof(default_data));
}
-void matrix_init_kb(void)
-{
-#ifndef VIA_ENABLE
- satisfaction_core_init();
-#endif // VIA_ENABLE
-
+void matrix_init_kb(void) {
rtcGetTime(&RTCD1, &last_timespec);
matrix_init_user();
oled_request_wakeup();
}
-#ifdef VIA_ENABLE
-void via_init_kb(void) {
- satisfaction_core_init();
-}
-#endif // VIA_ENABLE
-
void housekeeping_task_kb(void) {
rtcGetTime(&RTCD1, &last_timespec);
uint16_t minutes_since_midnight = last_timespec.millisecond / 1000 / 60;
diff --git a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.h b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.h
index 163aa27fad4..49d8991f3cd 100644
--- a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.h
+++ b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_core.h
@@ -8,7 +8,6 @@
#include
-#include "via.h" // only for EEPROM address
#include "satisfaction_keycodes.h"
#define EEPROM_ENABLED_ENCODER_MODES_OFFSET 0
diff --git a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_keycodes.h b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_keycodes.h
index 53f9facfc85..f7cfa2b9a6f 100644
--- a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_keycodes.h
+++ b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_keycodes.h
@@ -3,6 +3,8 @@
#pragma once
+#include "keycodes.h"
+
enum my_keycodes {
ENC_PRESS = QK_KB_0,
CLOCK_SET,
diff --git a/keyboards/cannonkeys/satisfaction75/config.h b/keyboards/cannonkeys/satisfaction75/config.h
index 28bc6b286a6..c78fc9296fa 100644
--- a/keyboards/cannonkeys/satisfaction75/config.h
+++ b/keyboards/cannonkeys/satisfaction75/config.h
@@ -34,15 +34,8 @@
// OLED timeout reimplemented in the keyboard-specific code
#define CUSTOM_OLED_TIMEOUT 60000
-// Custom config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
// Custom config Usage:
// 1 for enabled encoder modes (1 byte)
// 1 for OLED default mode (1 byte)
// 6 for 3x custom encoder settings, left, right, and press (18 bytes)
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 20
-
-// And if VIA isn't enabled, fall back to using standard QMK for configuration
-#ifndef VIA_ENABLE
-#define EECONFIG_KB_DATA_SIZE VIA_EEPROM_CUSTOM_CONFIG_SIZE
-#endif
+#define EECONFIG_KB_DATA_SIZE 20
diff --git a/keyboards/cannonkeys/satisfaction75_hs/config.h b/keyboards/cannonkeys/satisfaction75_hs/config.h
index 26c3e4080c4..0fe9b6f18f1 100644
--- a/keyboards/cannonkeys/satisfaction75_hs/config.h
+++ b/keyboards/cannonkeys/satisfaction75_hs/config.h
@@ -32,18 +32,11 @@
// OLED timeout reimplemented in the keyboard-specific code
#define CUSTOM_OLED_TIMEOUT 60000
-// Custom config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
// Custom config Usage:
// 1 for enabled encoder modes (1 byte)
// 1 for OLED default mode (1 byte)
// 6 for 3x custom encoder settings, left, right, and press (18 bytes)
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 20
-
-// And if VIA isn't enabled, fall back to using standard QMK for configuration
-#ifndef VIA_ENABLE
-#define EECONFIG_KB_DATA_SIZE VIA_EEPROM_CUSTOM_CONFIG_SIZE
-#endif
+#define EECONFIG_KB_DATA_SIZE 20
// VIA lighting is handled by the keyboard-level code
#define VIA_CUSTOM_LIGHTING_ENABLE
diff --git a/keyboards/cipulot/common/via_ec.c b/keyboards/cipulot/common/via_ec.c
index 7be6edd026a..4f5137f1442 100644
--- a/keyboards/cipulot/common/via_ec.c
+++ b/keyboards/cipulot/common/via_ec.c
@@ -16,13 +16,13 @@
#include "ec_switch_matrix.h"
#include "action.h"
#include "print.h"
-#include "via.h"
#ifdef SPLIT_KEYBOARD
# include "transactions.h"
#endif
#ifdef VIA_ENABLE
+# include "via.h"
void ec_rescale_values(uint8_t item);
void ec_save_threshold_data(uint8_t option);
diff --git a/keyboards/converter/adb_usb/adb_usb.c b/keyboards/converter/adb_usb/adb_usb.c
new file mode 100644
index 00000000000..2dca32998fe
--- /dev/null
+++ b/keyboards/converter/adb_usb/adb_usb.c
@@ -0,0 +1,13 @@
+// Copyright 2011 Jun Wako
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "led.h"
+#include "adb.h"
+
+bool led_update_kb(led_t led_state) {
+ bool res = led_update_user(led_state);
+ if(res) {
+ adb_host_kbd_led(~led_state.raw);
+ }
+ return res;
+}
diff --git a/keyboards/converter/adb_usb/led.c b/keyboards/converter/adb_usb/led.c
deleted file mode 100644
index 3ee64a8e7d3..00000000000
--- a/keyboards/converter/adb_usb/led.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-Copyright 2011 Jun Wako
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-#include
-#include
-#include "adb.h"
-#include "led.h"
-
-
-void led_set(uint8_t usb_led)
-{
- adb_host_kbd_led(~usb_led);
-}
diff --git a/keyboards/converter/adb_usb/rules.mk b/keyboards/converter/adb_usb/rules.mk
index b4a73249dde..75b7f1354f2 100644
--- a/keyboards/converter/adb_usb/rules.mk
+++ b/keyboards/converter/adb_usb/rules.mk
@@ -1,5 +1,5 @@
CUSTOM_MATRIX = yes
-SRC += matrix.c adb.c led.c
+SRC += matrix.c adb.c
# OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
diff --git a/keyboards/converter/thinkpad_t6x/info.json b/keyboards/converter/thinkpad_t6x/info.json
new file mode 100644
index 00000000000..5e7c564c4a7
--- /dev/null
+++ b/keyboards/converter/thinkpad_t6x/info.json
@@ -0,0 +1,116 @@
+{
+ "board": "GENERIC_RP_RP2040",
+ "bootloader": "rp2040",
+ "diode_direction": "COL2ROW",
+ "features": {
+ "bootmagic": true,
+ "extrakey": true,
+ "mousekey": true
+ },
+ "processor": "RP2040",
+ "ps2": {
+ "driver": "vendor",
+ "enabled": true,
+ "mouse_enabled": true
+ },
+ "layouts": {
+ "LAYOUT_iso": {
+ "layout": [
+ {"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
+ {"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
+ {"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
+ {"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
+ {"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
+ {"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
+ {"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
+ {"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
+ {"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
+ {"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
+ {"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
+ {"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
+ {"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
+ {"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
+ {"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
+ {"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
+ {"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
+ {"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
+ {"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
+ {"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
+ {"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
+ {"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
+ {"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
+ {"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
+ {"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
+ {"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
+ {"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
+ {"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
+ {"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
+ {"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
+ {"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
+ {"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
+ {"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
+ {"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
+ {"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
+ {"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
+ {"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
+ {"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
+ {"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
+ {"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
+ {"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
+ {"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
+ {"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
+ {"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
+ {"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
+ {"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
+ {"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
+ {"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
+ {"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
+ {"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
+ {"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
+ {"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
+ {"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
+ {"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
+ {"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
+ {"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
+ {"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
+ {"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
+ {"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
+ {"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
+ {"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
+ {"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
+ {"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
+ {"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
+ {"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
+ {"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
+ {"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
+ {"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
+ {"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
+ {"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
+ {"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
+ {"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
+ {"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
+ {"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
+ {"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
+ ]
+ }
+ }
+}
diff --git a/keyboards/converter/thinkpad_t6x/rpi_pico/keymaps/default/keymap.c b/keyboards/converter/thinkpad_t6x/keymaps/default/keymap.c
similarity index 100%
rename from keyboards/converter/thinkpad_t6x/rpi_pico/keymaps/default/keymap.c
rename to keyboards/converter/thinkpad_t6x/keymaps/default/keymap.c
diff --git a/keyboards/converter/thinkpad_t6x/pico_t61/keyboard.json b/keyboards/converter/thinkpad_t6x/pico_t61/keyboard.json
new file mode 100644
index 00000000000..78a6a8e3bed
--- /dev/null
+++ b/keyboards/converter/thinkpad_t6x/pico_t61/keyboard.json
@@ -0,0 +1,19 @@
+{
+ "manufacturer": "Frank Adams",
+ "keyboard_name": "converter/thinkpad_t6x/pico_t61",
+ "maintainer": "Al En",
+ "matrix_pins": {
+ "cols": ["GP27", "GP26", "GP17", "GP14", "GP12", "GP19", "GP18", "GP15", "GP13", "GP6", "GP16", "GP5", "GP28", "GP2", "GP4", "GP3"],
+ "rows": ["GP11", "GP22", "GP10", "GP21", "GP9", "GP20", "GP8", "GP7"]
+ },
+ "ps2": {
+ "clock_pin": "GP0",
+ "data_pin": "GP1"
+ },
+ "url": "https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard",
+ "usb": {
+ "device_version": "1.0.0",
+ "pid": "0xBACA",
+ "vid": "0xFEED"
+ }
+}
diff --git a/keyboards/converter/thinkpad_t6x/pico_t61/readme.md b/keyboards/converter/thinkpad_t6x/pico_t61/readme.md
new file mode 100644
index 00000000000..a849795e3fa
--- /dev/null
+++ b/keyboards/converter/thinkpad_t6x/pico_t61/readme.md
@@ -0,0 +1,27 @@
+# converter/thinkpad_t6x/pico_t61
+
+
+
+This is a converter PCB for Lenovo Thinkpad keyboards from T60, T400 and X200 series, based on the Raspberry Pi Pico W. The QMK implementation here is specific to the converter in the link below. Similar PCB designs to convert a Thinkpad keyboard to USB exist, but they use a different microcontroller and wiring of the keyboard connector with the MCU.
+
+* Keyboard Maintainer: [Al En](https://github.com/gitaen)
+* Hardware Supported: The linked converter PCB with keyboards from various Thinkpad models
+* Hardware Availability: [Custom PCB](https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard)
+
+Make example for this keyboard (after setting up your build environment):
+
+ make converter/thinkpad_t6x/pico_t61:default
+
+Flashing example for this keyboard:
+
+ make converter/thinkpad_t6x/pico_t61:default:flash
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+
+## Bootloader
+
+Enter the bootloader in 3 ways:
+
+* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (\`~) and plug in the keyboard
+* **Physical BOOTSEL button**: Hold down the BOOTSEL button on the Raspberry PiPico W and plug the keyboard
+* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
diff --git a/keyboards/converter/thinkpad_t6x/rpi_pico/keyboard.json b/keyboards/converter/thinkpad_t6x/rpi_pico/keyboard.json
index 4f876a4a94e..9c899db5340 100644
--- a/keyboards/converter/thinkpad_t6x/rpi_pico/keyboard.json
+++ b/keyboards/converter/thinkpad_t6x/rpi_pico/keyboard.json
@@ -2,130 +2,18 @@
"manufacturer": "strobo5",
"keyboard_name": "converter/thinkpad_t6x/rpi_pico",
"maintainer": "strobo5",
- "board": "GENERIC_RP_RP2040",
- "bootloader": "rp2040",
- "diode_direction": "COL2ROW",
- "features": {
- "bootmagic": true,
- "extrakey": true,
- "mousekey": true
- },
"matrix_pins": {
"cols": ["GP7", "GP9", "GP11", "GP13", "GP17", "GP16", "GP14", "GP12", "GP15", "GP8", "GP10", "GP6", "GP4", "GP2", "GP5", "GP3"],
"rows": ["GP20", "GP26", "GP22", "GP21", "GP18", "GP19", "GP27", "GP28"]
},
- "processor": "RP2040",
"ps2": {
"clock_pin": "GP1",
- "data_pin": "GP0",
- "driver": "vendor",
- "enabled": true,
- "mouse_enabled": true
+ "data_pin": "GP0"
},
"url": "https://github.com/strobo5/T61_PiPico_Scanner",
"usb": {
"device_version": "1.0.0",
"pid": "0x0000",
"vid": "0xFEED"
- },
- "layouts": {
- "LAYOUT_iso": {
- "layout": [
- {"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
- {"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
- {"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
- {"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
- {"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
- {"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
- {"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
- {"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
- {"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
- {"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
- {"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
- {"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
- {"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
- {"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
- {"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
- {"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
- {"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
- {"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
- {"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
- {"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
- {"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
- {"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
- {"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
- {"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
- {"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
- {"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
- {"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
- {"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
- {"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
- {"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
- {"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
- {"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
- {"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
- {"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
- {"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
- {"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
- {"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
- {"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
- {"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
- {"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
- {"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
- {"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
- {"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
- {"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
- {"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
- {"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
- {"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
- {"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
- {"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
- {"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
- {"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
- {"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
- {"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
- {"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
- {"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
- {"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
- {"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
- {"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
- {"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
- {"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
- {"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
- {"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
- {"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
- {"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
- {"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
- {"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
- {"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
- {"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
- {"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
- {"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
- {"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
- {"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
- {"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
- {"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
- {"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
- ]
- }
}
}
diff --git a/keyboards/converter/usb_usb/custom_matrix.cpp b/keyboards/converter/usb_usb/custom_matrix.cpp
index e1ef6955707..0c552a09bca 100644
--- a/keyboards/converter/usb_usb/custom_matrix.cpp
+++ b/keyboards/converter/usb_usb/custom_matrix.cpp
@@ -224,11 +224,14 @@ extern "C" {
}
}
- void led_set(uint8_t usb_led) {
- if (kbd1.isReady()) kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
- if (kbd2.isReady()) kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
- if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
- if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
- led_update_kb((led_t){.raw = usb_led});
+ bool led_update_kb(led_t led_state) {
+ bool res = led_update_user(led_state);
+ if(res) {
+ if (kbd1.isReady()) kbd1.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ if (kbd2.isReady()) kbd2.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ }
+ return res;
}
}
diff --git a/keyboards/ducky/one2sf/1967st/1967st.c b/keyboards/ducky/one2sf/1967st/1967st.c
new file mode 100644
index 00000000000..fe7855f63d9
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/1967st.c
@@ -0,0 +1,9 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+
+void bootloader_jump(void) {
+ // TODO: Work out how to jump to LDROM, for now just reset the board.
+ NVIC_SystemReset();
+}
diff --git a/keyboards/ducky/one2sf/1967st/ansi/keyboard.json b/keyboards/ducky/one2sf/1967st/ansi/keyboard.json
new file mode 100644
index 00000000000..42380addb1b
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/ansi/keyboard.json
@@ -0,0 +1,90 @@
+{
+ "keyboard_name": "One 2 SF ANSI",
+ "usb": {
+ "pid": "0x07AF",
+ "device_version": "0.0.1"
+ },
+ "layout_aliases": {
+ "LAYOUT_ansi": "LAYOUT"
+ },
+ "layouts": {
+ "LAYOUT": {
+ "layout": [
+ {"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
+ {"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
+ {"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
+ {"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
+ {"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
+ {"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
+ {"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
+ {"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
+ {"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
+ {"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
+ {"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
+ {"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
+ {"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
+ {"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
+
+ {"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
+
+ {"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
+ {"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
+ {"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
+ {"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
+ {"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
+ {"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
+ {"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
+ {"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
+ {"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
+ {"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
+ {"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
+ {"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
+ {"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
+ {"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
+
+ {"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
+
+ {"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
+ {"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
+ {"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
+ {"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
+ {"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
+ {"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
+ {"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
+ {"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
+ {"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
+ {"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
+ {"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
+ {"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
+ {"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
+
+ {"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
+
+ {"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
+ {"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
+ {"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
+ {"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
+ {"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
+ {"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
+ {"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
+ {"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
+ {"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
+ {"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
+ {"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
+ {"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
+ {"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
+
+ {"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
+ {"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
+ {"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
+ {"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
+ {"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
+ {"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
+ {"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
+ {"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
+ {"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
+ {"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
+ ]
+ }
+ }
+}
diff --git a/keyboards/ducky/one2sf/1967st/ansi/keymaps/default/config.h b/keyboards/ducky/one2sf/1967st/ansi/keymaps/default/config.h
new file mode 100644
index 00000000000..dc80ab8f9d4
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/ansi/keymaps/default/config.h
@@ -0,0 +1,12 @@
+// Copyright 2019 /u/KeepItUnder
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// place overrides here
+#define GRAVE_ESC_GUI_OVERRIDE
+#define MK_3_SPEED
+#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
+#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
+#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
+#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
diff --git a/keyboards/ducky/one2sf/keymaps/default_ansi/keymap.c b/keyboards/ducky/one2sf/1967st/ansi/keymaps/default/keymap.c
similarity index 62%
rename from keyboards/ducky/one2sf/keymaps/default_ansi/keymap.c
rename to keyboards/ducky/one2sf/1967st/ansi/keymaps/default/keymap.c
index d353f005ed0..680cc8261d9 100644
--- a/keyboards/ducky/one2sf/keymaps/default_ansi/keymap.c
+++ b/keyboards/ducky/one2sf/1967st/ansi/keymaps/default/keymap.c
@@ -1,34 +1,17 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2019 /u/KeepItUnder
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include QMK_KEYBOARD_H
-// LAYERS
enum Layer {
- _QWERTY = 0, // Standard QWERTY layer
- _FUNCTION, // Function key layer
- _COLOUR // RGB key layer
+ _QWERTY,
+ _FUNCTION,
+ _COLOUR
};
-#define _QW _QWERTY
-#define _FN _FUNCTION
-#define _CLR _COLOUR
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
- [_QWERTY] = LAYOUT_ansi(
- // 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ [_QWERTY] = LAYOUT(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
- [_FUNCTION] = LAYOUT_ansi(
+ [_FUNCTION] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, KC_END,
_______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
- _______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
+ _______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
),
- [_COLOUR] = LAYOUT_ansi(
+ [_COLOUR] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
diff --git a/keyboards/ducky/one2sf/1967st/chconf.h b/keyboards/ducky/one2sf/1967st/chconf.h
index 617be40dd90..54d5aa84c42 100644
--- a/keyboards/ducky/one2sf/1967st/chconf.h
+++ b/keyboards/ducky/one2sf/1967st/chconf.h
@@ -1,18 +1,5 @@
-/* Copyright 2020 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2020 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/keyboards/ducky/one2sf/1967st/config.h b/keyboards/ducky/one2sf/1967st/config.h
index 1bb511107db..a8bf4a03ef0 100644
--- a/keyboards/ducky/one2sf/1967st/config.h
+++ b/keyboards/ducky/one2sf/1967st/config.h
@@ -1,19 +1,5 @@
-/*
-Copyright 2019 /u/KeepItUnder
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
+// Copyright 2019 /u/KeepItUnder
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/keyboards/ducky/one2sf/1967st/info.json b/keyboards/ducky/one2sf/1967st/info.json
new file mode 100644
index 00000000000..634678affaf
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/info.json
@@ -0,0 +1,23 @@
+{
+ "manufacturer": "Ducky",
+ "maintainer": "f7urry",
+ "bootloader": "custom",
+ "usb": {
+ "vid": "0x445B"
+ },
+ "host": {
+ "default": {
+ "nkro": true
+ }
+ },
+ "matrix_pins": {
+ "cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15"],
+ "rows": ["D11", "B4", "B5", "B6", "B7"]
+ },
+ "diode_direction": "COL2ROW",
+ "features": {
+ "mousekey": true,
+ "extrakey": true,
+ "nkro": true
+ }
+}
diff --git a/keyboards/ducky/one2sf/1967st/iso/keyboard.json b/keyboards/ducky/one2sf/1967st/iso/keyboard.json
new file mode 100644
index 00000000000..f09f5aa7b29
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/iso/keyboard.json
@@ -0,0 +1,91 @@
+{
+ "keyboard_name": "One 2 SF ISO",
+ "usb": {
+ "pid": "0x07AE",
+ "device_version": "0.0.1"
+ },
+ "layout_aliases": {
+ "LAYOUT_iso": "LAYOUT"
+ },
+ "layouts": {
+ "LAYOUT": {
+ "layout": [
+ {"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
+ {"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
+ {"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
+ {"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
+ {"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
+ {"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
+ {"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
+ {"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
+ {"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
+ {"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
+ {"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
+ {"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
+ {"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
+ {"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
+
+ {"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
+
+ {"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
+ {"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
+ {"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
+ {"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
+ {"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
+ {"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
+ {"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
+ {"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
+ {"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
+ {"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
+ {"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
+ {"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
+ {"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
+
+ {"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
+
+ {"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
+ {"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
+ {"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
+ {"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
+ {"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
+ {"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
+ {"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
+ {"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
+ {"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
+ {"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
+ {"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
+ {"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
+ {"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
+ {"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
+
+ {"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
+
+ {"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
+ {"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
+ {"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
+ {"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
+ {"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
+ {"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
+ {"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
+ {"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
+ {"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
+ {"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
+ {"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
+ {"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
+ {"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
+ {"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
+
+ {"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
+ {"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
+ {"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
+ {"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
+ {"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
+ {"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
+ {"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
+ {"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
+ {"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
+ {"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
+ ]
+ }
+ }
+}
diff --git a/keyboards/ducky/one2sf/1967st/iso/keymaps/default/config.h b/keyboards/ducky/one2sf/1967st/iso/keymaps/default/config.h
new file mode 100644
index 00000000000..dc80ab8f9d4
--- /dev/null
+++ b/keyboards/ducky/one2sf/1967st/iso/keymaps/default/config.h
@@ -0,0 +1,12 @@
+// Copyright 2019 /u/KeepItUnder
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+// place overrides here
+#define GRAVE_ESC_GUI_OVERRIDE
+#define MK_3_SPEED
+#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
+#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
+#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
+#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
diff --git a/keyboards/ducky/one2sf/keymaps/default_iso/keymap.c b/keyboards/ducky/one2sf/1967st/iso/keymaps/default/keymap.c
similarity index 62%
rename from keyboards/ducky/one2sf/keymaps/default_iso/keymap.c
rename to keyboards/ducky/one2sf/1967st/iso/keymaps/default/keymap.c
index 3ec27fa54f8..482dae51ce1 100644
--- a/keyboards/ducky/one2sf/keymaps/default_iso/keymap.c
+++ b/keyboards/ducky/one2sf/1967st/iso/keymaps/default/keymap.c
@@ -1,34 +1,17 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2019 /u/KeepItUnder
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include QMK_KEYBOARD_H
-// LAYERS
enum Layer {
- _QWERTY = 0, // Standard QWERTY layer
- _FUNCTION, // Function key layer
- _COLOUR // RGB key layer
+ _QWERTY,
+ _FUNCTION,
+ _COLOUR
};
-#define _QW _QWERTY
-#define _FN _FUNCTION
-#define _CLR _COLOUR
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
- [_QWERTY] = LAYOUT_iso(
- // 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ [_QWERTY] = LAYOUT(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
- [_FUNCTION] = LAYOUT_iso(
+ [_FUNCTION] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, KC_HOME,
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, _______, KC_END,
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
- _______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
+ _______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
),
- [_COLOUR] = LAYOUT_iso(
+ [_COLOUR] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
diff --git a/keyboards/ducky/one2sf/1967st/keyboard.json b/keyboards/ducky/one2sf/1967st/keyboard.json
deleted file mode 100644
index 093793d4c88..00000000000
--- a/keyboards/ducky/one2sf/1967st/keyboard.json
+++ /dev/null
@@ -1,269 +0,0 @@
-{
- "keyboard_name": "One 2 SF",
- "manufacturer": "Ducky",
- "maintainer": "f7urry",
- "usb": {
- "vid": "0x445B",
- "pid": "0x07AF",
- "device_version": "0.0.1"
- },
- "host": {
- "default": {
- "nkro": true
- }
- },
- "matrix_pins": {
- "cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15", "B8"],
- "rows": ["D11", "B4", "B5", "B6", "B7"]
- },
- "diode_direction": "COL2ROW",
- "dip_switch": {
- "matrix_grid": [ [0,14], [1,14], [2,14], [3,14] ]
- },
- "features": {
- "bootmagic": true,
- "mousekey": true,
- "extrakey": true,
- "nkro": true,
- "dip_switch": true
- },
- "layouts": {
- "LAYOUT_all": {
- "layout": [
- {"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
- {"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
- {"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
- {"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
- {"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
- {"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
- {"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
- {"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
- {"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
- {"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
- {"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
- {"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
- {"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
- {"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
-
- {"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
-
- {"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
- {"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
- {"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
- {"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
- {"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
- {"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
- {"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
- {"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
- {"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
- {"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
- {"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
- {"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
- {"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
- {"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
-
- {"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
-
- {"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
- {"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
- {"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
- {"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
- {"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
- {"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
- {"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
- {"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
- {"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
- {"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
- {"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
- {"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
- {"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
- {"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 2, "w": 1.25},
-
- {"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
-
- {"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
- {"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
- {"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
- {"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
- {"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
- {"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
- {"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
- {"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
- {"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
- {"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
- {"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
- {"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
- {"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
- {"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
-
- {"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
- {"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
- {"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
- {"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
- {"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
- {"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
- {"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
- {"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
- {"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
- {"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
- ]
- },
- "LAYOUT_ansi": {
- "layout": [
- {"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
- {"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
- {"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
- {"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
- {"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
- {"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
- {"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
- {"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
- {"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
- {"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
- {"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
- {"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
- {"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
- {"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
-
- {"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
-
- {"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
- {"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
- {"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
- {"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
- {"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
- {"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
- {"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
- {"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
- {"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
- {"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
- {"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
- {"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
- {"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
- {"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
-
- {"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
-
- {"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
- {"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
- {"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
- {"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
- {"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
- {"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
- {"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
- {"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
- {"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
- {"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
- {"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
- {"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
- {"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
-
- {"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
-
- {"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
- {"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
- {"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
- {"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
- {"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
- {"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
- {"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
- {"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
- {"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
- {"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
- {"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
- {"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
- {"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
-
- {"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
- {"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
- {"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
- {"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
- {"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
- {"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
- {"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
- {"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
- {"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
- {"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
- ]
- },
- "LAYOUT_iso": {
- "layout": [
- {"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
- {"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
- {"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
- {"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
- {"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
- {"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
- {"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
- {"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
- {"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
- {"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
- {"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
- {"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
- {"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
- {"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
-
- {"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
-
- {"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
- {"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
- {"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
- {"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
- {"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
- {"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
- {"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
- {"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
- {"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
- {"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
- {"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
- {"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
- {"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
-
- {"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
-
- {"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
- {"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
- {"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
- {"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
- {"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
- {"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
- {"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
- {"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
- {"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
- {"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
- {"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
- {"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
- {"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
- {"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
-
- {"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
-
- {"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
- {"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
- {"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
- {"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
- {"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
- {"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
- {"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
- {"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
- {"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
- {"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
- {"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
- {"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
- {"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
- {"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
-
- {"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
- {"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
- {"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
- {"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
- {"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
- {"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
- {"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
- {"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
- {"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
- {"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
- ]
- }
- }
-}
diff --git a/keyboards/ducky/one2sf/1967st/matrix_diagram.md b/keyboards/ducky/one2sf/1967st/matrix_diagram.md
deleted file mode 100644
index 7fdc0a82ceb..00000000000
--- a/keyboards/ducky/one2sf/1967st/matrix_diagram.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Matrix Diagram for Ducky One 2 SF
-
-```
-┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐┌───┐
-│00 │01 │02 │03 │04 │05 │06 │07 │08 │09 │0A │0B │0C │0D ││0E │
-├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤├───┤ ┌─────┐
-│10 │11 │12 │13 │14 │15 │16 │17 │18 │19 │1A │1B │1C │1D ││1E │ │ │
-├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤├───┤ ┌──┴┐2D │
-│20 │21 │22 │23 │24 │25 │26 │27 │28 │29 │2A │2B │2D ││2E │ │2C │ │
-├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─────┬──┴┼───┘ └───┴────┘
-│30 │31 │32 │33 │34 │35 │36 │37 │38 │39 │3A │3B │3C │3D │ ISO Enter
-├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴──┬┴──┬┴───┬───┼───┼───┐
-│40 │41 │42 │45 │49 │4A │4B │4C │4D │4E │
-└────┴────┴────┴────────────────────────┴───┴───┴────┴───┴───┴───┘
-┌────────┐
-│30 │ 2.25u LShift
-└────────┘
-```
diff --git a/keyboards/ducky/one2sf/1967st/mcuconf.h b/keyboards/ducky/one2sf/1967st/mcuconf.h
index 12e9d2a82dc..e8975cf13ff 100644
--- a/keyboards/ducky/one2sf/1967st/mcuconf.h
+++ b/keyboards/ducky/one2sf/1967st/mcuconf.h
@@ -43,7 +43,7 @@
#define NUC123_USB_USE_USB0 TRUE
#define NUC123_USB_USE_USB1 TRUE
-#define NUC123_SERIAL_USE_UART0 TRUE
+#define NUC123_SERIAL_USE_UART0 FALSE
#define NUC123_SERIAL_CLKSRC NUC123_SERIAL_CLKSRC_HSI
#define NUC123_MCUCONF
diff --git a/keyboards/ducky/one2sf/1967st/readme.md b/keyboards/ducky/one2sf/1967st/readme.md
index cb3739efbb7..5038d62ada4 100644
--- a/keyboards/ducky/one2sf/1967st/readme.md
+++ b/keyboards/ducky/one2sf/1967st/readme.md
@@ -2,18 +2,16 @@
A 65% keyboard by Ducky.
-This firmware was tested on the Ducky One 2 SF 1967ST version.
-
* Keyboard Maintainer: [f7urry](https://github.com/f7urry)
* Hardware Supported: Ducky One 2 SF RGB (DKON1967ST), NUC123SD4AN0 + MBI5043GP
- * Only ANSI layout is supported at this time
- * ISO compiles but is **untested**
* VIA still WIP.
* RGB LEDs are currently disabled until the driver is merged.
+ * DIP switches are disabled due to hardware incompatibilities
## Compiling the Firmware:
- make ducky/one2sf/1967st:default
+ make ducky/one2sf/1967st/ansi:default
+ make ducky/one2sf/1967st/iso:default
## Accessing Bootloader Mode
@@ -24,11 +22,16 @@ To enter the 1967ST bootloader to flash, boot the keyboard while holding D+L.
There are then two ways to flash the keyboard:
pip install --user nuvoton-isp
- nuvoisp -f ducky_one2sf_ansi.bin
+ nuvoisp -f ducky_one2sf_1967st_ansi_default.bin
Alternatively you can use elfmimi's [nu-isp-cli](https://lib.rs/crates/nu-isp-cli) which is more complete than nuvoisp and allows flashing .hex files as well.
cargo install nu-isp-cli
- nu-isp-cli flash ducky_one2sf_ansi.bin
+ nu-isp-cli flash ducky_one2sf_1967st_ansi_default.bin
+
+ or
+
+ make ducky/one2sf/1967st/ansi:default:flash
+ make ducky/one2sf/1967st/iso:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
diff --git a/keyboards/ducky/one2sf/1967st/rules.mk b/keyboards/ducky/one2sf/1967st/rules.mk
index 5eb1c44f8a1..1ff38c97eb6 100644
--- a/keyboards/ducky/one2sf/1967st/rules.mk
+++ b/keyboards/ducky/one2sf/1967st/rules.mk
@@ -15,3 +15,6 @@ BOARD = NUC123SD4AN0
MCU = cortex-m0
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 6
+
+# Needs elevated access to 0416:3f00 on Linux
+PROGRAM_CMD = nu-isp-cli flash $(BUILD_DIR)/$(TARGET).bin
diff --git a/keyboards/ducky/one2sf/keymaps/default/config.h b/keyboards/ducky/one2sf/keymaps/default/config.h
deleted file mode 100644
index b052c604f5a..00000000000
--- a/keyboards/ducky/one2sf/keymaps/default/config.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-
-// place overrides here
-#define GRAVE_ESC_GUI_OVERRIDE
-#define MK_3_SPEED
-#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
-#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
-#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
-#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
diff --git a/keyboards/ducky/one2sf/keymaps/default/keymap.c b/keyboards/ducky/one2sf/keymaps/default/keymap.c
deleted file mode 100644
index 91a644d9725..00000000000
--- a/keyboards/ducky/one2sf/keymaps/default/keymap.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#include QMK_KEYBOARD_H
-
-// LAYERS
-enum Layer {
- _QWERTY = 0, // Standard QWERTY layer
- _FUNCTION, // Function key layer
- _COLOUR // RGB key layer
-};
-#define _QW _QWERTY
-#define _FN _FUNCTION
-#define _CLR _COLOUR
-
-const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-
- [_QWERTY] = LAYOUT_all(
- // 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
- KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
- KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
- KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
- KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
- ),
-
- [_FUNCTION] = LAYOUT_all(
- KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
- _______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUSE, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
- _______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RIGHT, KC_PGDN, KC_END, _______, _______, KC_END,
- _______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
- _______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
- ),
-
- [_COLOUR] = LAYOUT_all(
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
- ),
-
-};
diff --git a/keyboards/ducky/one2sf/keymaps/default_ansi/config.h b/keyboards/ducky/one2sf/keymaps/default_ansi/config.h
deleted file mode 100644
index b052c604f5a..00000000000
--- a/keyboards/ducky/one2sf/keymaps/default_ansi/config.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-
-// place overrides here
-#define GRAVE_ESC_GUI_OVERRIDE
-#define MK_3_SPEED
-#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
-#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
-#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
-#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
diff --git a/keyboards/ducky/one2sf/keymaps/default_iso/config.h b/keyboards/ducky/one2sf/keymaps/default_iso/config.h
deleted file mode 100644
index b052c604f5a..00000000000
--- a/keyboards/ducky/one2sf/keymaps/default_iso/config.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2019 /u/KeepItUnder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-
-// place overrides here
-#define GRAVE_ESC_GUI_OVERRIDE
-#define MK_3_SPEED
-#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
-#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
-#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
-#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
diff --git a/keyboards/gmmk/gmmk2/p96/ansi/ansi.c b/keyboards/gmmk/gmmk2/p96/ansi/ansi.c
index dc61fd813f9..c758b857987 100644
--- a/keyboards/gmmk/gmmk2/p96/ansi/ansi.c
+++ b/keyboards/gmmk/gmmk2/p96/ansi/ansi.c
@@ -152,27 +152,3 @@ const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
{1, SW10_CS16, SW10_CS17, SW10_CS18} // 120, LED 20
};
#endif
-
-#ifdef EEPROM_ENABLE
-
-#include "spi_master.h"
-
-void spi_init(void) {
- static bool is_initialised = false;
- if (!is_initialised) {
- is_initialised = true;
-
- // Try releasing special pins for a short time
- gpio_set_pin_input(SPI_SCK_PIN);
- gpio_set_pin_input(SPI_MOSI_PIN);
- gpio_set_pin_input(SPI_MISO_PIN);
-
- chThdSleepMilliseconds(10);
-
- palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST | PAL_WB32_CURRENT_LEVEL3);
- palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
- palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
- }
-}
-
-#endif
diff --git a/keyboards/gmmk/gmmk2/p96/iso/iso.c b/keyboards/gmmk/gmmk2/p96/iso/iso.c
index 7da63dfae6d..4e2cd854c7f 100644
--- a/keyboards/gmmk/gmmk2/p96/iso/iso.c
+++ b/keyboards/gmmk/gmmk2/p96/iso/iso.c
@@ -153,27 +153,3 @@ const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
{1, SW10_CS16, SW10_CS17, SW10_CS18} // 120, LED 20
};
#endif
-
-#ifdef EEPROM_ENABLE
-
-#include "spi_master.h"
-
-void spi_init(void) {
- static bool is_initialised = false;
- if (!is_initialised) {
- is_initialised = true;
-
- // Try releasing special pins for a short time
- gpio_set_pin_input(SPI_SCK_PIN);
- gpio_set_pin_input(SPI_MOSI_PIN);
- gpio_set_pin_input(SPI_MISO_PIN);
-
- chThdSleepMilliseconds(10);
-
- palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST | PAL_WB32_CURRENT_LEVEL3);
- palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
- palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
- }
-}
-
-#endif
diff --git a/keyboards/handwired/onekey/keymaps/nvm_test/keymap.c b/keyboards/handwired/onekey/keymaps/nvm_test/keymap.c
new file mode 100644
index 00000000000..777bf6b37de
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/nvm_test/keymap.c
@@ -0,0 +1,13 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include QMK_KEYBOARD_H
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)};
+
+void keyboard_post_init_user(void) {
+ // Customise these values to desired behaviour
+ debug_enable = true;
+ debug_matrix = true;
+ // debug_keyboard=true;
+ // debug_mouse=true;
+}
diff --git a/keyboards/handwired/onekey/keymaps/nvm_test/keymap.json b/keyboards/handwired/onekey/keymaps/nvm_test/keymap.json
new file mode 100644
index 00000000000..5f328b3364e
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/nvm_test/keymap.json
@@ -0,0 +1,10 @@
+{
+ "config": {
+ "features": {
+ "console": true
+ }
+ },
+ "modules": [
+ "qmk/nvm_test"
+ ]
+}
diff --git a/keyboards/handwired/onekey/keymaps/virtser/keymap.c b/keyboards/handwired/onekey/keymaps/virtser/keymap.c
new file mode 100644
index 00000000000..68f891511f6
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/virtser/keymap.c
@@ -0,0 +1,40 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include QMK_KEYBOARD_H
+#include "virtser.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ LAYOUT_ortho_1x1(KC_A)
+};
+
+static uint32_t counter = 0;
+
+void virtser_recv(const uint8_t ch) {
+ static const char *lut = "0123456789ABCDEF";
+
+ counter++;
+
+ virtser_send(lut[(ch & 0xF0) >> 4]);
+ virtser_send(lut[ch & 0xF]);
+}
+
+#ifdef CONSOLE_ENABLE
+
+void keyboard_post_init_user(void) {
+ // Customise these values to desired behaviour
+ debug_enable = true;
+ // debug_matrix=true;
+ // debug_keyboard=true;
+ // debug_mouse=true;
+}
+
+void housekeeping_task_user(void) {
+ static uint32_t last = 0;
+ if (timer_elapsed32(last) > 1000) {
+ uprintf("recv: %ld!\n", counter);
+
+ last = timer_read32();
+ }
+}
+
+#endif
diff --git a/keyboards/handwired/onekey/keymaps/virtser/keymap.json b/keyboards/handwired/onekey/keymaps/virtser/keymap.json
new file mode 100644
index 00000000000..766633055e9
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/virtser/keymap.json
@@ -0,0 +1,12 @@
+{
+ "config": {
+ "usb": {
+ "shared_endpoint": {
+ "keyboard": true
+ }
+ },
+ "features": {
+ "virtser": true
+ }
+ }
+}
diff --git a/keyboards/hs60/v2/ansi/ansi.h b/keyboards/hs60/v2/ansi/ansi.h
index d7296c38c18..2fbe06e7f4d 100644
--- a/keyboards/hs60/v2/ansi/ansi.h
+++ b/keyboards/hs60/v2/ansi/ansi.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "../../wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/hs60/v2/ansi/config.h b/keyboards/hs60/v2/ansi/config.h
index e96c36313cb..0bc637db9df 100644
--- a/keyboards/hs60/v2/ansi/config.h
+++ b/keyboards/hs60/v2/ansi/config.h
@@ -72,6 +72,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/hs60/v2/hhkb/config.h b/keyboards/hs60/v2/hhkb/config.h
index 6a6fa375bca..1c8c422b44a 100644
--- a/keyboards/hs60/v2/hhkb/config.h
+++ b/keyboards/hs60/v2/hhkb/config.h
@@ -72,6 +72,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/hs60/v2/hhkb/hhkb.h b/keyboards/hs60/v2/hhkb/hhkb.h
index d7296c38c18..2fbe06e7f4d 100644
--- a/keyboards/hs60/v2/hhkb/hhkb.h
+++ b/keyboards/hs60/v2/hhkb/hhkb.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "../../wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/hs60/v2/iso/config.h b/keyboards/hs60/v2/iso/config.h
index 5f1a55b1d11..521dff36b97 100644
--- a/keyboards/hs60/v2/iso/config.h
+++ b/keyboards/hs60/v2/iso/config.h
@@ -69,6 +69,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/hs60/v2/iso/iso.h b/keyboards/hs60/v2/iso/iso.h
index d7296c38c18..2fbe06e7f4d 100644
--- a/keyboards/hs60/v2/iso/iso.h
+++ b/keyboards/hs60/v2/iso/iso.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "../../wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/keebwerk/mega/ansi/ansi.h b/keyboards/keebwerk/mega/ansi/ansi.h
index 7f1a26c10e8..24d2bd65456 100755
--- a/keyboards/keebwerk/mega/ansi/ansi.h
+++ b/keyboards/keebwerk/mega/ansi/ansi.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "../wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/keebwerk/mega/ansi/config.h b/keyboards/keebwerk/mega/ansi/config.h
index 8a110a91dc3..01c13184a89 100755
--- a/keyboards/keebwerk/mega/ansi/config.h
+++ b/keyboards/keebwerk/mega/ansi/config.h
@@ -70,6 +70,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/keychron/common/keychron_common.h b/keyboards/keychron/common/keychron_common.h
index 648a5d3371a..fbc7aa40091 100644
--- a/keyboards/keychron/common/keychron_common.h
+++ b/keyboards/keychron/common/keychron_common.h
@@ -20,10 +20,6 @@
#include
#include "action.h"
-#ifdef VIA_ENABLE
-# include "via.h"
-#endif
-
#include "quantum_keycodes.h"
enum custom_keycodes {
diff --git a/keyboards/keycult/keycult_tkl/keyboard.json b/keyboards/keycult/keycult_tkl/keyboard.json
index 81687f13bde..130c6cd333e 100644
--- a/keyboards/keycult/keycult_tkl/keyboard.json
+++ b/keyboards/keycult/keycult_tkl/keyboard.json
@@ -21,187 +21,836 @@
"pid": "0x6336",
"vid": "0x8968"
},
- "community_layouts": ["tkl_ansi", "tkl_ansi_tsangan"],
+ "community_layouts": ["tkl_ansi", "tkl_ansi_tsangan", "tkl_ansi_split_bs_rshift", "tkl_ansi_tsangan_split_bs_rshift", "tkl_iso", "tkl_iso_split_bs_rshift", "tkl_iso_tsangan", "tkl_iso_tsangan_split_bs_rshift"],
"layouts": {
+ "LAYOUT_all": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "x": 13, "y": 1.25 },
+ { "matrix": [0, 13], "x": 14, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
+ { "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 1], "x": 1.25, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 13], "x": 14, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
+ { "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
+ { "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
"LAYOUT_tkl_ansi": {
"layout": [
- {"matrix": [0, 0], "x": 0, "y": 0},
- {"matrix": [0, 1], "x": 2, "y": 0},
- {"matrix": [0, 2], "x": 3, "y": 0},
- {"matrix": [0, 3], "x": 4, "y": 0},
- {"matrix": [0, 4], "x": 5, "y": 0},
- {"matrix": [0, 5], "x": 6.5, "y": 0},
- {"matrix": [0, 6], "x": 7.5, "y": 0},
- {"matrix": [0, 7], "x": 8.5, "y": 0},
- {"matrix": [0, 8], "x": 9.5, "y": 0},
- {"matrix": [0, 9], "x": 11, "y": 0},
- {"matrix": [0, 10], "x": 12, "y": 0},
- {"matrix": [0, 11], "x": 13, "y": 0},
- {"matrix": [0, 12], "x": 14, "y": 0},
- {"matrix": [0, 14], "x": 15.25, "y": 0},
- {"matrix": [0, 15], "x": 16.25, "y": 0},
- {"matrix": [0, 16], "x": 17.25, "y": 0},
- {"matrix": [1, 0], "x": 0, "y": 1.25},
- {"matrix": [1, 1], "x": 1, "y": 1.25},
- {"matrix": [1, 2], "x": 2, "y": 1.25},
- {"matrix": [1, 3], "x": 3, "y": 1.25},
- {"matrix": [1, 4], "x": 4, "y": 1.25},
- {"matrix": [1, 5], "x": 5, "y": 1.25},
- {"matrix": [1, 6], "x": 6, "y": 1.25},
- {"matrix": [1, 7], "x": 7, "y": 1.25},
- {"matrix": [1, 8], "x": 8, "y": 1.25},
- {"matrix": [1, 9], "x": 9, "y": 1.25},
- {"matrix": [1, 10], "x": 10, "y": 1.25},
- {"matrix": [1, 11], "x": 11, "y": 1.25},
- {"matrix": [1, 12], "x": 12, "y": 1.25},
- {"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
- {"matrix": [1, 14], "x": 15.25, "y": 1.25},
- {"matrix": [1, 15], "x": 16.25, "y": 1.25},
- {"matrix": [1, 16], "x": 17.25, "y": 1.25},
- {"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
- {"matrix": [2, 1], "x": 1.5, "y": 2.25},
- {"matrix": [2, 2], "x": 2.5, "y": 2.25},
- {"matrix": [2, 3], "x": 3.5, "y": 2.25},
- {"matrix": [2, 4], "x": 4.5, "y": 2.25},
- {"matrix": [2, 5], "x": 5.5, "y": 2.25},
- {"matrix": [2, 6], "x": 6.5, "y": 2.25},
- {"matrix": [2, 7], "x": 7.5, "y": 2.25},
- {"matrix": [2, 8], "x": 8.5, "y": 2.25},
- {"matrix": [2, 9], "x": 9.5, "y": 2.25},
- {"matrix": [2, 10], "x": 10.5, "y": 2.25},
- {"matrix": [2, 11], "x": 11.5, "y": 2.25},
- {"matrix": [2, 12], "x": 12.5, "y": 2.25},
- {"matrix": [3, 12], "x": 13.5, "y": 2.25, "w": 1.5},
- {"matrix": [2, 14], "x": 15.25, "y": 2.25},
- {"matrix": [2, 15], "x": 16.25, "y": 2.25},
- {"matrix": [2, 16], "x": 17.25, "y": 2.25},
- {"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
- {"matrix": [3, 1], "x": 1.75, "y": 3.25},
- {"matrix": [3, 2], "x": 2.75, "y": 3.25},
- {"matrix": [3, 3], "x": 3.75, "y": 3.25},
- {"matrix": [3, 4], "x": 4.75, "y": 3.25},
- {"matrix": [3, 5], "x": 5.75, "y": 3.25},
- {"matrix": [3, 6], "x": 6.75, "y": 3.25},
- {"matrix": [3, 7], "x": 7.75, "y": 3.25},
- {"matrix": [3, 8], "x": 8.75, "y": 3.25},
- {"matrix": [3, 9], "x": 9.75, "y": 3.25},
- {"matrix": [3, 10], "x": 10.75, "y": 3.25},
- {"matrix": [3, 11], "x": 11.75, "y": 3.25},
- {"matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25},
- {"matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25},
- {"matrix": [4, 2], "x": 2.25, "y": 4.25},
- {"matrix": [4, 3], "x": 3.25, "y": 4.25},
- {"matrix": [4, 4], "x": 4.25, "y": 4.25},
- {"matrix": [4, 5], "x": 5.25, "y": 4.25},
- {"matrix": [4, 6], "x": 6.25, "y": 4.25},
- {"matrix": [4, 7], "x": 7.25, "y": 4.25},
- {"matrix": [4, 8], "x": 8.25, "y": 4.25},
- {"matrix": [4, 9], "x": 9.25, "y": 4.25},
- {"matrix": [4, 10], "x": 10.25, "y": 4.25},
- {"matrix": [4, 11], "x": 11.25, "y": 4.25},
- {"matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 2.75},
- {"matrix": [4, 15], "x": 16.25, "y": 4.25},
- {"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25},
- {"matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25},
- {"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25},
- {"matrix": [5, 6], "x": 3.75, "y": 5.25, "w": 6.25},
- {"matrix": [5, 10], "x": 10, "y": 5.25, "w": 1.25},
- {"matrix": [5, 11], "x": 11.25, "y": 5.25, "w": 1.25},
- {"matrix": [5, 12], "x": 12.5, "y": 5.25, "w": 1.25},
- {"matrix": [5, 13], "x": 13.75, "y": 5.25, "w": 1.25},
- {"matrix": [5, 14], "x": 15.25, "y": 5.25},
- {"matrix": [5, 15], "x": 16.25, "y": 5.25},
- {"matrix": [5, 16], "x": 17.25, "y": 5.25}
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
+ { "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
+ { "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
+ { "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_ansi_split_bs_rshift": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "x": 13, "y": 1.25 },
+ { "matrix": [0, 13], "x": 14, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
+ { "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 13], "x": 14, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
+ { "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
+ { "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_ansi_tsangan": {
"layout": [
- {"matrix": [0, 0], "x": 0, "y": 0},
- {"matrix": [0, 1], "x": 2, "y": 0},
- {"matrix": [0, 2], "x": 3, "y": 0},
- {"matrix": [0, 3], "x": 4, "y": 0},
- {"matrix": [0, 4], "x": 5, "y": 0},
- {"matrix": [0, 5], "x": 6.5, "y": 0},
- {"matrix": [0, 6], "x": 7.5, "y": 0},
- {"matrix": [0, 7], "x": 8.5, "y": 0},
- {"matrix": [0, 8], "x": 9.5, "y": 0},
- {"matrix": [0, 9], "x": 11, "y": 0},
- {"matrix": [0, 10], "x": 12, "y": 0},
- {"matrix": [0, 11], "x": 13, "y": 0},
- {"matrix": [0, 12], "x": 14, "y": 0},
- {"matrix": [0, 14], "x": 15.25, "y": 0},
- {"matrix": [0, 15], "x": 16.25, "y": 0},
- {"matrix": [0, 16], "x": 17.25, "y": 0},
- {"matrix": [1, 0], "x": 0, "y": 1.25},
- {"matrix": [1, 1], "x": 1, "y": 1.25},
- {"matrix": [1, 2], "x": 2, "y": 1.25},
- {"matrix": [1, 3], "x": 3, "y": 1.25},
- {"matrix": [1, 4], "x": 4, "y": 1.25},
- {"matrix": [1, 5], "x": 5, "y": 1.25},
- {"matrix": [1, 6], "x": 6, "y": 1.25},
- {"matrix": [1, 7], "x": 7, "y": 1.25},
- {"matrix": [1, 8], "x": 8, "y": 1.25},
- {"matrix": [1, 9], "x": 9, "y": 1.25},
- {"matrix": [1, 10], "x": 10, "y": 1.25},
- {"matrix": [1, 11], "x": 11, "y": 1.25},
- {"matrix": [1, 12], "x": 12, "y": 1.25},
- {"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
- {"matrix": [1, 14], "x": 15.25, "y": 1.25},
- {"matrix": [1, 15], "x": 16.25, "y": 1.25},
- {"matrix": [1, 16], "x": 17.25, "y": 1.25},
- {"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
- {"matrix": [2, 1], "x": 1.5, "y": 2.25},
- {"matrix": [2, 2], "x": 2.5, "y": 2.25},
- {"matrix": [2, 3], "x": 3.5, "y": 2.25},
- {"matrix": [2, 4], "x": 4.5, "y": 2.25},
- {"matrix": [2, 5], "x": 5.5, "y": 2.25},
- {"matrix": [2, 6], "x": 6.5, "y": 2.25},
- {"matrix": [2, 7], "x": 7.5, "y": 2.25},
- {"matrix": [2, 8], "x": 8.5, "y": 2.25},
- {"matrix": [2, 9], "x": 9.5, "y": 2.25},
- {"matrix": [2, 10], "x": 10.5, "y": 2.25},
- {"matrix": [2, 11], "x": 11.5, "y": 2.25},
- {"matrix": [2, 12], "x": 12.5, "y": 2.25},
- {"matrix": [3, 12], "x": 13.5, "y": 2.25, "w": 1.5},
- {"matrix": [2, 14], "x": 15.25, "y": 2.25},
- {"matrix": [2, 15], "x": 16.25, "y": 2.25},
- {"matrix": [2, 16], "x": 17.25, "y": 2.25},
- {"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
- {"matrix": [3, 1], "x": 1.75, "y": 3.25},
- {"matrix": [3, 2], "x": 2.75, "y": 3.25},
- {"matrix": [3, 3], "x": 3.75, "y": 3.25},
- {"matrix": [3, 4], "x": 4.75, "y": 3.25},
- {"matrix": [3, 5], "x": 5.75, "y": 3.25},
- {"matrix": [3, 6], "x": 6.75, "y": 3.25},
- {"matrix": [3, 7], "x": 7.75, "y": 3.25},
- {"matrix": [3, 8], "x": 8.75, "y": 3.25},
- {"matrix": [3, 9], "x": 9.75, "y": 3.25},
- {"matrix": [3, 10], "x": 10.75, "y": 3.25},
- {"matrix": [3, 11], "x": 11.75, "y": 3.25},
- {"matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25},
- {"matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25},
- {"matrix": [4, 2], "x": 2.25, "y": 4.25},
- {"matrix": [4, 3], "x": 3.25, "y": 4.25},
- {"matrix": [4, 4], "x": 4.25, "y": 4.25},
- {"matrix": [4, 5], "x": 5.25, "y": 4.25},
- {"matrix": [4, 6], "x": 6.25, "y": 4.25},
- {"matrix": [4, 7], "x": 7.25, "y": 4.25},
- {"matrix": [4, 8], "x": 8.25, "y": 4.25},
- {"matrix": [4, 9], "x": 9.25, "y": 4.25},
- {"matrix": [4, 10], "x": 10.25, "y": 4.25},
- {"matrix": [4, 11], "x": 11.25, "y": 4.25},
- {"matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 2.75},
- {"matrix": [4, 15], "x": 16.25, "y": 4.25},
- {"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.5},
- {"matrix": [5, 1], "x": 1.5, "y": 5.25},
- {"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.5},
- {"matrix": [5, 6], "x": 4, "y": 5.25, "w": 7},
- {"matrix": [5, 11], "x": 11, "y": 5.25, "w": 1.5},
- {"matrix": [5, 12], "x": 12.5, "y": 5.25},
- {"matrix": [5, 13], "x": 13.5, "y": 5.25, "w": 1.5},
- {"matrix": [5, 14], "x": 15.25, "y": 5.25},
- {"matrix": [5, 15], "x": 16.25, "y": 5.25},
- {"matrix": [5, 16], "x": 17.25, "y": 5.25}
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
+ { "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "x": 1.5, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
+ { "matrix": [5, 12], "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_ansi_tsangan_split_bs_rshift": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "x": 13, "y": 1.25 },
+ { "matrix": [0, 13], "x": 14, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
+ { "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 13], "x": 14, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "x": 1.5, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
+ { "matrix": [5, 12], "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_iso": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 12], "x": 12.75, "y": 3.25 },
+ { "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
+ { "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 1], "x": 1.25, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
+ { "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
+ { "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_iso_split_bs_rshift": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "x": 13, "y": 1.25 },
+ { "matrix": [0, 13], "x": 14, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 12], "x": 12.75, "y": 3.25 },
+ { "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
+ { "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 1], "x": 1.25, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 13], "x": 14, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
+ { "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
+ { "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_iso_tsangan": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 12], "x": 12.75, "y": 3.25 },
+ { "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
+ { "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 1], "x": 1.25, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "x": 1.5, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
+ { "matrix": [5, 12], "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
+ ]
+ },
+ "LAYOUT_tkl_iso_tsangan_split_bs_rshift": {
+ "layout": [
+ { "matrix": [0, 0], "x": 0, "y": 0 },
+ { "matrix": [0, 1], "x": 2, "y": 0 },
+ { "matrix": [0, 2], "x": 3, "y": 0 },
+ { "matrix": [0, 3], "x": 4, "y": 0 },
+ { "matrix": [0, 4], "x": 5, "y": 0 },
+ { "matrix": [0, 5], "x": 6.5, "y": 0 },
+ { "matrix": [0, 6], "x": 7.5, "y": 0 },
+ { "matrix": [0, 7], "x": 8.5, "y": 0 },
+ { "matrix": [0, 8], "x": 9.5, "y": 0 },
+ { "matrix": [0, 9], "x": 11, "y": 0 },
+ { "matrix": [0, 10], "x": 12, "y": 0 },
+ { "matrix": [0, 11], "x": 13, "y": 0 },
+ { "matrix": [0, 12], "x": 14, "y": 0 },
+ { "matrix": [0, 14], "x": 15.25, "y": 0 },
+ { "matrix": [0, 15], "x": 16.25, "y": 0 },
+ { "matrix": [0, 16], "x": 17.25, "y": 0 },
+ { "matrix": [1, 0], "x": 0, "y": 1.25 },
+ { "matrix": [1, 1], "x": 1, "y": 1.25 },
+ { "matrix": [1, 2], "x": 2, "y": 1.25 },
+ { "matrix": [1, 3], "x": 3, "y": 1.25 },
+ { "matrix": [1, 4], "x": 4, "y": 1.25 },
+ { "matrix": [1, 5], "x": 5, "y": 1.25 },
+ { "matrix": [1, 6], "x": 6, "y": 1.25 },
+ { "matrix": [1, 7], "x": 7, "y": 1.25 },
+ { "matrix": [1, 8], "x": 8, "y": 1.25 },
+ { "matrix": [1, 9], "x": 9, "y": 1.25 },
+ { "matrix": [1, 10], "x": 10, "y": 1.25 },
+ { "matrix": [1, 11], "x": 11, "y": 1.25 },
+ { "matrix": [1, 12], "x": 12, "y": 1.25 },
+ { "matrix": [1, 13], "x": 13, "y": 1.25 },
+ { "matrix": [0, 13], "x": 14, "y": 1.25 },
+ { "matrix": [1, 14], "x": 15.25, "y": 1.25 },
+ { "matrix": [1, 15], "x": 16.25, "y": 1.25 },
+ { "matrix": [1, 16], "x": 17.25, "y": 1.25 },
+ { "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
+ { "matrix": [2, 1], "x": 1.5, "y": 2.25 },
+ { "matrix": [2, 2], "x": 2.5, "y": 2.25 },
+ { "matrix": [2, 3], "x": 3.5, "y": 2.25 },
+ { "matrix": [2, 4], "x": 4.5, "y": 2.25 },
+ { "matrix": [2, 5], "x": 5.5, "y": 2.25 },
+ { "matrix": [2, 6], "x": 6.5, "y": 2.25 },
+ { "matrix": [2, 7], "x": 7.5, "y": 2.25 },
+ { "matrix": [2, 8], "x": 8.5, "y": 2.25 },
+ { "matrix": [2, 9], "x": 9.5, "y": 2.25 },
+ { "matrix": [2, 10], "x": 10.5, "y": 2.25 },
+ { "matrix": [2, 11], "x": 11.5, "y": 2.25 },
+ { "matrix": [2, 12], "x": 12.5, "y": 2.25 },
+ { "matrix": [2, 14], "x": 15.25, "y": 2.25 },
+ { "matrix": [2, 15], "x": 16.25, "y": 2.25 },
+ { "matrix": [2, 16], "x": 17.25, "y": 2.25 },
+ { "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
+ { "matrix": [3, 1], "x": 1.75, "y": 3.25 },
+ { "matrix": [3, 2], "x": 2.75, "y": 3.25 },
+ { "matrix": [3, 3], "x": 3.75, "y": 3.25 },
+ { "matrix": [3, 4], "x": 4.75, "y": 3.25 },
+ { "matrix": [3, 5], "x": 5.75, "y": 3.25 },
+ { "matrix": [3, 6], "x": 6.75, "y": 3.25 },
+ { "matrix": [3, 7], "x": 7.75, "y": 3.25 },
+ { "matrix": [3, 8], "x": 8.75, "y": 3.25 },
+ { "matrix": [3, 9], "x": 9.75, "y": 3.25 },
+ { "matrix": [3, 10], "x": 10.75, "y": 3.25 },
+ { "matrix": [3, 11], "x": 11.75, "y": 3.25 },
+ { "matrix": [3, 12], "x": 12.75, "y": 3.25 },
+ { "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
+ { "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
+ { "matrix": [4, 1], "x": 1.25, "y": 4.25 },
+ { "matrix": [4, 2], "x": 2.25, "y": 4.25 },
+ { "matrix": [4, 3], "x": 3.25, "y": 4.25 },
+ { "matrix": [4, 4], "x": 4.25, "y": 4.25 },
+ { "matrix": [4, 5], "x": 5.25, "y": 4.25 },
+ { "matrix": [4, 6], "x": 6.25, "y": 4.25 },
+ { "matrix": [4, 7], "x": 7.25, "y": 4.25 },
+ { "matrix": [4, 8], "x": 8.25, "y": 4.25 },
+ { "matrix": [4, 9], "x": 9.25, "y": 4.25 },
+ { "matrix": [4, 10], "x": 10.25, "y": 4.25 },
+ { "matrix": [4, 11], "x": 11.25, "y": 4.25 },
+ { "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
+ { "matrix": [4, 13], "x": 14, "y": 4.25 },
+ { "matrix": [4, 15], "x": 16.25, "y": 4.25 },
+ { "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
+ { "matrix": [5, 1], "x": 1.5, "y": 5.25 },
+ { "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
+ { "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
+ { "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
+ { "matrix": [5, 12], "x": 12.5, "y": 5.25 },
+ { "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
+ { "matrix": [5, 14], "x": 15.25, "y": 5.25 },
+ { "matrix": [5, 15], "x": 16.25, "y": 5.25 },
+ { "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
}
}
diff --git a/keyboards/keycult/keycult_tkl/keymaps/default/keymap.c b/keyboards/keycult/keycult_tkl/keymaps/default/keymap.c
index 0f67593ea0b..3bd4d8e9464 100644
--- a/keyboards/keycult/keycult_tkl/keymaps/default/keymap.c
+++ b/keyboards/keycult/keycult_tkl/keymaps/default/keymap.c
@@ -16,20 +16,21 @@
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-[0] = LAYOUT_tkl_ansi( /* Base */
- KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SCRL, KC_PAUS,
- KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
- KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
- KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
- KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
- KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
+[0] = LAYOUT_all( /* Base */
+ KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SCRL, KC_PAUS,
-[1] = LAYOUT_tkl_ansi( /* FN */
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, KC_VOLD, KC_MUTE,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_INS, KC_HOME, KC_PGUP,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+ KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP,
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
+
+[1] = LAYOUT_all( /* FN */
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, KC_VOLD, KC_MUTE,
+
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
-
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
diff --git a/keyboards/magic_force/mf17/config.h b/keyboards/magic_force/mf17/config.h
new file mode 100644
index 00000000000..474aaecf53d
--- /dev/null
+++ b/keyboards/magic_force/mf17/config.h
@@ -0,0 +1,9 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#define WS2812_PWM_DRIVER PWMD15
+#define WS2812_PWM_CHANNEL 1
+#define WS2812_PWM_PAL_MODE 0
+#define WS2812_PWM_DMA_STREAM STM32_DMA1_STREAM5
+#define WS2812_PWM_DMA_CHANNEL 5
diff --git a/keyboards/magic_force/mf17/halconf.h b/keyboards/magic_force/mf17/halconf.h
new file mode 100644
index 00000000000..1cef6b6b286
--- /dev/null
+++ b/keyboards/magic_force/mf17/halconf.h
@@ -0,0 +1,7 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#define HAL_USE_PWM TRUE
+
+#include_next
diff --git a/keyboards/magic_force/mf17/keyboard.json b/keyboards/magic_force/mf17/keyboard.json
index c0f0e6bd57e..ac759c84638 100644
--- a/keyboards/magic_force/mf17/keyboard.json
+++ b/keyboards/magic_force/mf17/keyboard.json
@@ -28,6 +28,7 @@
"rgb_matrix": true
},
"ws2812": {
+ "driver": "pwm",
"pin": "A2"
},
"rgb_matrix": {
@@ -78,23 +79,23 @@
},
"driver": "ws2812",
"layout": [
- {"flags": 1, "matrix": [4, 1], "x": 37, "y": 64},
- {"flags": 1, "matrix": [4, 2], "x": 150, "y": 64},
- {"flags": 1, "matrix": [4, 3], "x": 224, "y": 56},
- {"flags": 1, "matrix": [3, 0], "x": 0, "y": 48},
- {"flags": 1, "matrix": [3, 1], "x": 75, "y": 48},
- {"flags": 1, "matrix": [3, 2], "x": 150, "y": 48},
- {"flags": 1, "matrix": [2, 0], "x": 0, "y": 32},
- {"flags": 1, "matrix": [2, 1], "x": 75, "y": 32},
- {"flags": 1, "matrix": [2, 2], "x": 150, "y": 32},
- {"flags": 1, "matrix": [2, 3], "x": 224, "y": 24},
- {"flags": 1, "matrix": [1, 0], "x": 0, "y": 16},
- {"flags": 1, "matrix": [1, 1], "x": 75, "y": 16},
- {"flags": 1, "matrix": [1, 2], "x": 150, "y": 16},
- {"flags": 1, "matrix": [0, 0], "x": 0, "y": 0},
- {"flags": 1, "matrix": [0, 1], "x": 75, "y": 0},
- {"flags": 1, "matrix": [0, 2], "x": 150, "y": 0},
- {"flags": 1, "matrix": [0, 3], "x": 224, "y": 0}
+ {"flags": 4, "matrix": [4, 1], "x": 37, "y": 64},
+ {"flags": 4, "matrix": [4, 2], "x": 150, "y": 64},
+ {"flags": 4, "matrix": [4, 3], "x": 224, "y": 56},
+ {"flags": 4, "matrix": [3, 0], "x": 0, "y": 48},
+ {"flags": 4, "matrix": [3, 1], "x": 75, "y": 48},
+ {"flags": 4, "matrix": [3, 2], "x": 150, "y": 48},
+ {"flags": 4, "matrix": [2, 0], "x": 0, "y": 32},
+ {"flags": 4, "matrix": [2, 1], "x": 75, "y": 32},
+ {"flags": 4, "matrix": [2, 2], "x": 150, "y": 32},
+ {"flags": 4, "matrix": [2, 3], "x": 224, "y": 24},
+ {"flags": 4, "matrix": [1, 0], "x": 0, "y": 16},
+ {"flags": 4, "matrix": [1, 1], "x": 75, "y": 16},
+ {"flags": 4, "matrix": [1, 2], "x": 150, "y": 16},
+ {"flags": 4, "matrix": [0, 0], "x": 0, "y": 0},
+ {"flags": 4, "matrix": [0, 1], "x": 75, "y": 0},
+ {"flags": 4, "matrix": [0, 2], "x": 150, "y": 0},
+ {"flags": 4, "matrix": [0, 3], "x": 224, "y": 0}
],
"max_brightness": 180,
"sleep": true
diff --git a/keyboards/magic_force/mf17/keymaps/default/keymap.c b/keyboards/magic_force/mf17/keymaps/default/keymap.c
index 867d292b88c..d9f9536904a 100755
--- a/keyboards/magic_force/mf17/keymaps/default/keymap.c
+++ b/keyboards/magic_force/mf17/keymaps/default/keymap.c
@@ -1,32 +1,20 @@
-/*
-Copyright 2012,2013 gezhaoyou
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
+// Copyright 2012,2013 gezhaoyou
+// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
- [0] = LAYOUT_numpad_5x4(
- KC_NUM_LOCK, KC_PSLS, KC_PAST, LT(1, KC_PMNS),
- KC_P7, KC_P8, KC_P9,
- KC_P4, KC_P5, KC_P6, KC_PPLS,
- KC_P1, KC_P2, KC_P3,
- KC_P0, KC_PDOT, KC_PENT),
- [1] = LAYOUT_numpad_5x4(
- KC_TRNS, KC_CALCULATOR, KC_BSPC, KC_TRNS,
- RM_NEXT, RM_VALU, RM_HUEU,
- RM_SPDD, RM_TOGG, RM_SPDU, QK_BOOTLOADER,
- RM_PREV, RM_VALD, RM_HUED,
- KC_TRNS, KC_TRNS, QK_CLEAR_EEPROM),
+ [0] = LAYOUT_numpad_5x4(
+ KC_NUM, KC_PSLS, KC_PAST, LT(1, KC_PMNS),
+ KC_P7, KC_P8, KC_P9,
+ KC_P4, KC_P5, KC_P6, KC_PPLS,
+ KC_P1, KC_P2, KC_P3,
+ KC_P0, KC_PDOT, KC_PENT
+ ),
+ [1] = LAYOUT_numpad_5x4(
+ _______, KC_CALC, KC_BSPC, _______,
+ RM_NEXT, RM_VALU, RM_HUEU,
+ RM_SPDD, RM_TOGG, RM_SPDU, QK_BOOT,
+ RM_PREV, RM_VALD, RM_HUED,
+ _______, _______, EE_CLR
+ ),
};
diff --git a/keyboards/magic_force/mf17/mcuconf.h b/keyboards/magic_force/mf17/mcuconf.h
new file mode 100644
index 00000000000..313134465c6
--- /dev/null
+++ b/keyboards/magic_force/mf17/mcuconf.h
@@ -0,0 +1,10 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#include_next
+
+#undef STM32_PWM_USE_TIM15
+#define STM32_PWM_USE_TIM15 TRUE
+
+#define STM32_TIM15_SUPPRESS_ISR
diff --git a/keyboards/magic_force/mf17/readme.md b/keyboards/magic_force/mf17/readme.md
index bb75cadfe9c..ed3a67702ec 100644
--- a/keyboards/magic_force/mf17/readme.md
+++ b/keyboards/magic_force/mf17/readme.md
@@ -4,6 +4,7 @@ A customizable 17 keyboard, support both HOTSWAP and SOLDER.
* Keyboard Maintainer: [gezhaoyou](https://github.com/gezhaoyou)
* Hardware Supported: [gezhaoyou](https://github.com/gezhaoyou)
+
Make example for this keyboard (after setting up your build environment):
make magic_force/mf17:default
diff --git a/keyboards/mkh_studio/bully/keyboard.json b/keyboards/mkh_studio/bully/keyboard.json
index 5102ffa632f..fbdf90c6d54 100644
--- a/keyboards/mkh_studio/bully/keyboard.json
+++ b/keyboards/mkh_studio/bully/keyboard.json
@@ -26,8 +26,11 @@
"resync": true
}
},
+ "layout_aliases": {
+ "LAYOUT": "LAYOUT_all"
+ },
"layouts": {
- "LAYOUT": {
+ "LAYOUT_all": {
"layout": [
{"matrix": [0, 0], "w": 1.5, "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1.5, "y": 0},
@@ -69,9 +72,107 @@
{"matrix": [3, 0], "w": 1.25, "x": 0, "y": 3},
{"matrix": [3, 1], "w": 1.25, "x": 1.25, "y": 3},
{"matrix": [3, 2], "w": 1.25, "x": 2.5, "y": 3},
- {"matrix": [3, 3], "w": 3, "x": 3.75, "y": 3, "h": 0.5},
- {"matrix": [3, 5], "w": 6, "x": 3.75, "y": 3.5, "h": 0.5},
- {"matrix": [3, 6], "w": 3, "x": 6.75, "y": 3, "h": 0.5},
+ {"matrix": [3, 3], "w": 2.5, "x": 3.75, "y": 3},
+ {"matrix": [3, 5], "w": 1, "x": 6.25, "y": 3},
+ {"matrix": [3, 6], "w": 2.5, "x": 7.25, "y": 3},
+ {"matrix": [3, 8], "w": 1.25, "x": 9.75, "y": 3},
+ {"matrix": [3, 9], "w": 1.25, "x": 11, "y": 3},
+ {"matrix": [3, 10], "w": 1.25, "x": 12.25, "y": 3}
+ ]
+ },
+
+ "LAYOUT_split_space": {
+ "layout": [
+ {"matrix": [0, 0], "w": 1.5, "x": 0, "y": 0},
+ {"matrix": [0, 1], "x": 1.5, "y": 0},
+ {"matrix": [0, 2], "x": 2.5, "y": 0},
+ {"matrix": [0, 3], "x": 3.5, "y": 0},
+ {"matrix": [0, 4], "x": 4.5, "y": 0},
+ {"matrix": [0, 5], "x": 5.5, "y": 0},
+ {"matrix": [0, 6], "x": 6.5, "y": 0},
+ {"matrix": [0, 7], "x": 7.5, "y": 0},
+ {"matrix": [0, 8], "x": 8.5, "y": 0},
+ {"matrix": [0, 9], "x": 9.5, "y": 0},
+ {"matrix": [0, 10], "x": 10.5, "y": 0},
+ {"matrix": [0, 11], "x": 11.5, "y": 0},
+ {"matrix": [3, 11], "x": 12.5, "y": 0},
+ {"matrix": [1, 0], "w": 1.75, "x": 0, "y": 1},
+ {"matrix": [1, 1], "x": 1.75, "y": 1},
+ {"matrix": [1, 2], "x": 2.75, "y": 1},
+ {"matrix": [1, 3], "x": 3.75, "y": 1},
+ {"matrix": [1, 4], "x": 4.75, "y": 1},
+ {"matrix": [1, 5], "x": 5.75, "y": 1},
+ {"matrix": [1, 6], "x": 6.75, "y": 1},
+ {"matrix": [1, 7], "x": 7.75, "y": 1},
+ {"matrix": [1, 8], "x": 8.75, "y": 1},
+ {"matrix": [1, 9], "x": 9.75, "y": 1},
+ {"matrix": [1, 10], "x": 10.75, "y": 1},
+ {"matrix": [1, 11], "w": 1.75, "x": 11.75, "y": 1},
+ {"matrix": [2, 0], "w": 2.25, "x": 0, "y": 2},
+ {"matrix": [2, 1], "x": 2.25, "y": 2},
+ {"matrix": [2, 2], "x": 3.25, "y": 2},
+ {"matrix": [2, 3], "x": 4.25, "y": 2},
+ {"matrix": [2, 4], "x": 5.25, "y": 2},
+ {"matrix": [2, 5], "x": 6.25, "y": 2},
+ {"matrix": [2, 6], "x": 7.25, "y": 2},
+ {"matrix": [2, 7], "x": 8.25, "y": 2},
+ {"matrix": [2, 8], "x": 9.25, "y": 2},
+ {"matrix": [2, 9], "x": 10.25, "y": 2},
+ {"matrix": [2, 10], "x": 11.25, "y": 2},
+ {"matrix": [2, 11], "w": 1.25, "x": 12.25, "y": 2},
+ {"matrix": [3, 0], "w": 1.25, "x": 0, "y": 3},
+ {"matrix": [3, 1], "w": 1.25, "x": 1.25, "y": 3},
+ {"matrix": [3, 2], "w": 1.25, "x": 2.5, "y": 3},
+ {"matrix": [3, 3], "w": 3, "x": 3.75, "y": 3},
+ {"matrix": [3, 6], "w": 3, "x": 6.75, "y": 3},
+ {"matrix": [3, 8], "w": 1.25, "x": 9.75, "y": 3},
+ {"matrix": [3, 9], "w": 1.25, "x": 11, "y": 3},
+ {"matrix": [3, 10], "w": 1.25, "x": 12.25, "y": 3}
+ ]
+ },
+ "LAYOUT_full_space": {
+ "layout": [
+ {"matrix": [0, 0], "w": 1.5, "x": 0, "y": 0},
+ {"matrix": [0, 1], "x": 1.5, "y": 0},
+ {"matrix": [0, 2], "x": 2.5, "y": 0},
+ {"matrix": [0, 3], "x": 3.5, "y": 0},
+ {"matrix": [0, 4], "x": 4.5, "y": 0},
+ {"matrix": [0, 5], "x": 5.5, "y": 0},
+ {"matrix": [0, 6], "x": 6.5, "y": 0},
+ {"matrix": [0, 7], "x": 7.5, "y": 0},
+ {"matrix": [0, 8], "x": 8.5, "y": 0},
+ {"matrix": [0, 9], "x": 9.5, "y": 0},
+ {"matrix": [0, 10], "x": 10.5, "y": 0},
+ {"matrix": [0, 11], "x": 11.5, "y": 0},
+ {"matrix": [3, 11], "x": 12.5, "y": 0},
+ {"matrix": [1, 0], "w": 1.75, "x": 0, "y": 1},
+ {"matrix": [1, 1], "x": 1.75, "y": 1},
+ {"matrix": [1, 2], "x": 2.75, "y": 1},
+ {"matrix": [1, 3], "x": 3.75, "y": 1},
+ {"matrix": [1, 4], "x": 4.75, "y": 1},
+ {"matrix": [1, 5], "x": 5.75, "y": 1},
+ {"matrix": [1, 6], "x": 6.75, "y": 1},
+ {"matrix": [1, 7], "x": 7.75, "y": 1},
+ {"matrix": [1, 8], "x": 8.75, "y": 1},
+ {"matrix": [1, 9], "x": 9.75, "y": 1},
+ {"matrix": [1, 10], "x": 10.75, "y": 1},
+ {"matrix": [1, 11], "w": 1.75, "x": 11.75, "y": 1},
+ {"matrix": [2, 0], "w": 2.25, "x": 0, "y": 2},
+ {"matrix": [2, 1], "x": 2.25, "y": 2},
+ {"matrix": [2, 2], "x": 3.25, "y": 2},
+ {"matrix": [2, 3], "x": 4.25, "y": 2},
+ {"matrix": [2, 4], "x": 5.25, "y": 2},
+ {"matrix": [2, 5], "x": 6.25, "y": 2},
+ {"matrix": [2, 6], "x": 7.25, "y": 2},
+ {"matrix": [2, 7], "x": 8.25, "y": 2},
+ {"matrix": [2, 8], "x": 9.25, "y": 2},
+ {"matrix": [2, 9], "x": 10.25, "y": 2},
+ {"matrix": [2, 10], "x": 11.25, "y": 2},
+ {"matrix": [2, 11], "w": 1.25, "x": 12.25, "y": 2},
+ {"matrix": [3, 0], "w": 1.25, "x": 0, "y": 3},
+ {"matrix": [3, 1], "w": 1.25, "x": 1.25, "y": 3},
+ {"matrix": [3, 2], "w": 1.25, "x": 2.5, "y": 3},
+ {"matrix": [3, 5], "w": 6, "x": 3.75, "y": 3},
{"matrix": [3, 8], "w": 1.25, "x": 9.75, "y": 3},
{"matrix": [3, 9], "w": 1.25, "x": 11, "y": 3},
{"matrix": [3, 10], "w": 1.25, "x": 12.25, "y": 3}
diff --git a/keyboards/mkh_studio/bully/keymaps/default/keymap.c b/keyboards/mkh_studio/bully/keymaps/default/keymap.c
index a5d25185e10..19d3faf2246 100644
--- a/keyboards/mkh_studio/bully/keymaps/default/keymap.c
+++ b/keyboards/mkh_studio/bully/keymaps/default/keymap.c
@@ -4,19 +4,19 @@
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
- [0] = LAYOUT(
+ [0] = LAYOUT_all(
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_BSPC,
LT(2, KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
KC_LCTL, KC_LGUI, KC_LALT, LT(1, KC_SPC), KC_SPC, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL
),
- [1] = LAYOUT(
+ [1] = LAYOUT_all(
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS, QK_BOOT,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BSLS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, LT(2, KC_SPC), KC_HOME, KC_PGDN, KC_END
),
- [2] = LAYOUT(
+ [2] = LAYOUT_all(
KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_PGUP, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_TRNS, KC_TRNS,
KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
diff --git a/keyboards/nifty_numpad/keyboard.json b/keyboards/nifty_numpad/keyboard.json
index 3dce0cca356..a0e8cc4412b 100644
--- a/keyboards/nifty_numpad/keyboard.json
+++ b/keyboards/nifty_numpad/keyboard.json
@@ -6,8 +6,6 @@
"diode_direction": "ROW2COL",
"features": {
"bootmagic": true,
- "command": false,
- "console": false,
"extrakey": true,
"mousekey": true,
"nkro": true,
diff --git a/keyboards/nifty_numpad/nifty_numpad.c b/keyboards/nifty_numpad/nifty_numpad.c
index 5e487fed7f3..60f76e744ab 100644
--- a/keyboards/nifty_numpad/nifty_numpad.c
+++ b/keyboards/nifty_numpad/nifty_numpad.c
@@ -221,9 +221,5 @@ void eeconfig_init_kb_datablock(void) {
config.idle_rgb_matrix = default_idle_rgb_matrix;
eeconfig_update_kb_datablock(&config, 0, EECONFIG_KB_DATA_SIZE);
-
-# if (EECONFIG_USER_DATA_SIZE) > 0
- eeconfig_init_user_datablock();
-# endif // EECONFIG_USER_DATA_SIZE
#endif // RGB_IDLE_ENABLE
}
diff --git a/keyboards/novelkeys/nk87/config.h b/keyboards/novelkeys/nk87/config.h
index ff9e05cbad0..7943fd8d4d5 100755
--- a/keyboards/novelkeys/nk87/config.h
+++ b/keyboards/novelkeys/nk87/config.h
@@ -1,76 +1,9 @@
-/*
-Copyright 2020 Yiancar
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
+// Copyright 2020 Yiancar
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
-/* Backlight options */
-
-#define RGB_BACKLIGHT_ENABLED 1
-
-#define RGB_BACKLIGHT_NK87
-
-// they aren't really used if RGB_BACKLIGHT_HS60 defined
-#define RGB_BACKLIGHT_USE_SPLIT_BACKSPACE 0
-#define RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT 0
-#define RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT 0
-#define RGB_BACKLIGHT_USE_7U_SPACEBAR 0
-#define RGB_BACKLIGHT_USE_ISO_ENTER 0
-#define RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS 0
-
-// disable backlight when USB suspended (PC sleep/hibernate/shutdown)
-#define RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED 0
-
-// disable backlight after timeout in minutes, 0 = no timeout
-#define RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT 0
-
-// the default brightness
-#define RGB_BACKLIGHT_BRIGHTNESS 255
-
-// the default effect (RGB test)
-#define RGB_BACKLIGHT_EFFECT 6
-
-// the default effect speed (0-3)
-#define RGB_BACKLIGHT_EFFECT_SPEED 0
-
-// the default color1 and color2
-#define RGB_BACKLIGHT_COLOR_1 { .h = 0, .s = 255 }
-#define RGB_BACKLIGHT_COLOR_2 { .h = 127, .s = 255 }
-
#define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND
#define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_SDA
-#define IS31FL3733_LED_COUNT 128
-// These define which keys in the matrix are alphas/mods
-// Used for backlight effects so colors are different for
-// alphas vs. mods
-// Each value is for a row, bit 0 is column 0
-// Alpha=0 Mod=1
-// Rows are shifted one down, F-row cannot be dynamically modified at the moment.
-#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_0 0b1110000000000000
-#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_1 0b1100000000000001
-#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_2 0b0010000000000001
-#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_3 0b1001000000000001
-#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 0b1111100000000111
-
-#define RGB_BACKLIGHT_CAPS_LOCK_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-#define RGB_BACKLIGHT_LAYER_1_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0K5_OHM
+#define IS31FL3733_CS_PULLDOWN IS31FL3733_PDR_0K5_OHM
diff --git a/keyboards/novelkeys/nk87/halconf.h b/keyboards/novelkeys/nk87/halconf.h
index fb0c2142644..9a17aad812e 100644
--- a/keyboards/novelkeys/nk87/halconf.h
+++ b/keyboards/novelkeys/nk87/halconf.h
@@ -1,33 +1,7 @@
-/* Copyright 2020 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/*
- * This file was auto-generated by:
- * `qmk chibios-confmigrate -i keyboards/nk87/halconf.h -r platforms/chibios/QMK_PROTON_C/configs/halconf.h`
- */
-
+// Copyright 2020 Yiancar
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
-#define HAL_USE_PWM FALSE
-
-#define HAL_USE_SPI FALSE
-
-#define PAL_USE_CALLBACKS FALSE
-
-#define PAL_USE_WAIT FALSE
+#define HAL_USE_I2C TRUE
#include_next
-
diff --git a/keyboards/novelkeys/nk87/keyboard.json b/keyboards/novelkeys/nk87/keyboard.json
index 8b7f8fed4da..0c31ac0202b 100755
--- a/keyboards/novelkeys/nk87/keyboard.json
+++ b/keyboards/novelkeys/nk87/keyboard.json
@@ -12,6 +12,7 @@
"bootmagic": true,
"extrakey": true,
"mousekey": true,
+ "rgb_matrix": true,
"nkro": true
},
"matrix_pins": {
@@ -21,7 +22,152 @@
"diode_direction": "COL2ROW",
"processor": "STM32F303",
"bootloader": "stm32-dfu",
- "board": "QMK_PROTON_C",
+ "rgb_matrix": {
+ "driver": "is31fl3733",
+ "sleep": true,
+ "animations": {
+ "alphas_mods": true,
+ "gradient_up_down": true,
+ "gradient_left_right": true,
+ "breathing": true,
+ "band_sat": true,
+ "band_val": true,
+ "band_pinwheel_sat": true,
+ "band_pinwheel_val": true,
+ "band_spiral_sat": true,
+ "band_spiral_val": true,
+ "cycle_all": true,
+ "cycle_left_right": true,
+ "cycle_up_down": true,
+ "cycle_out_in": true,
+ "cycle_out_in_dual": true,
+ "rainbow_moving_chevron": true,
+ "cycle_pinwheel": true,
+ "cycle_spiral": true,
+ "dual_beacon": true,
+ "rainbow_beacon": true,
+ "rainbow_pinwheels": true,
+ "raindrops": true,
+ "jellybean_raindrops": true,
+ "hue_breathing": true,
+ "hue_pendulum": true,
+ "hue_wave": true,
+ "pixel_fractal": true,
+ "pixel_flow": true,
+ "pixel_rain": true,
+ "typing_heatmap": true,
+ "digital_rain": true,
+ "solid_reactive_simple": true,
+ "solid_reactive": true,
+ "solid_reactive_wide": true,
+ "solid_reactive_multiwide": true,
+ "solid_reactive_cross": true,
+ "solid_reactive_multicross": true,
+ "solid_reactive_nexus": true,
+ "solid_reactive_multinexus": true,
+ "splash": true,
+ "multisplash": true,
+ "solid_splash": true,
+ "solid_multisplash": true
+ },
+ "layout": [
+ { "flags": 4, "matrix": [0, 0], "x": 6, "y": 8 },
+ { "flags": 4, "matrix": [0, 1], "x": 21, "y": 8 },
+ { "flags": 4, "matrix": [0, 2], "x": 33, "y": 8 },
+ { "flags": 4, "matrix": [0, 3], "x": 45, "y": 8 },
+ { "flags": 4, "matrix": [0, 4], "x": 57, "y": 8 },
+ { "flags": 4, "matrix": [0, 5], "x": 74, "y": 8 },
+ { "flags": 4, "matrix": [0, 6], "x": 86, "y": 8 },
+ { "flags": 4, "matrix": [0, 7], "x": 98, "y": 8 },
+ { "flags": 4, "matrix": [0, 8], "x": 110, "y": 8 },
+ { "flags": 4, "matrix": [0, 9], "x": 125, "y": 8 },
+ { "flags": 4, "matrix": [0, 10], "x": 137, "y": 8 },
+ { "flags": 4, "matrix": [0, 11], "x": 150, "y": 8 },
+ { "flags": 4, "matrix": [0, 12], "x": 161, "y": 8 },
+ { "flags": 4, "matrix": [0, 13], "x": 176, "y": 8 },
+ { "flags": 4, "matrix": [0, 14], "x": 192, "y": 8 },
+ { "flags": 4, "matrix": [0, 15], "x": 204, "y": 8 },
+ { "flags": 4, "matrix": [0, 16], "x": 217, "y": 8 },
+
+ { "flags": 4, "matrix": [1, 0], "x": 6, "y": 21 },
+ { "flags": 4, "matrix": [1, 1], "x": 18, "y": 21 },
+ { "flags": 4, "matrix": [1, 2], "x": 30, "y": 21 },
+ { "flags": 4, "matrix": [1, 3], "x": 43, "y": 21 },
+ { "flags": 4, "matrix": [1, 4], "x": 55, "y": 21 },
+ { "flags": 4, "matrix": [1, 5], "x": 67, "y": 21 },
+ { "flags": 4, "matrix": [1, 6], "x": 79, "y": 21 },
+ { "flags": 4, "matrix": [1, 7], "x": 92, "y": 21 },
+ { "flags": 4, "matrix": [1, 8], "x": 104, "y": 21 },
+ { "flags": 4, "matrix": [1, 9], "x": 116, "y": 21 },
+ { "flags": 4, "matrix": [1, 10], "x": 128, "y": 21 },
+ { "flags": 4, "matrix": [1, 11], "x": 141, "y": 21 },
+ { "flags": 4, "matrix": [1, 12], "x": 153, "y": 21 },
+ { "flags": 4, "matrix": [1, 13], "x": 171, "y": 21 },
+ { "flags": 4, "matrix": [1, 14], "x": 192, "y": 21 },
+ { "flags": 4, "matrix": [1, 15], "x": 204, "y": 21 },
+ { "flags": 4, "matrix": [1, 16], "x": 217, "y": 21 },
+
+ { "flags": 4, "matrix": [2, 0], "x": 9, "y": 31 },
+ { "flags": 4, "matrix": [2, 1], "x": 24, "y": 31 },
+ { "flags": 4, "matrix": [2, 2], "x": 36, "y": 31 },
+ { "flags": 4, "matrix": [2, 3], "x": 48, "y": 31 },
+ { "flags": 4, "matrix": [2, 4], "x": 61, "y": 31 },
+ { "flags": 4, "matrix": [2, 5], "x": 73, "y": 31 },
+ { "flags": 4, "matrix": [2, 6], "x": 86, "y": 31 },
+ { "flags": 4, "matrix": [2, 7], "x": 98, "y": 31 },
+ { "flags": 4, "matrix": [2, 8], "x": 110, "y": 31 },
+ { "flags": 4, "matrix": [2, 9], "x": 122, "y": 31 },
+ { "flags": 4, "matrix": [2, 10], "x": 134, "y": 31 },
+ { "flags": 4, "matrix": [2, 11], "x": 146, "y": 31 },
+ { "flags": 4, "matrix": [2, 12], "x": 159, "y": 31 },
+ { "flags": 4, "matrix": [3, 12], "x": 174, "y": 31 },
+ { "flags": 4, "matrix": [2, 14], "x": 192, "y": 31 },
+ { "flags": 4, "matrix": [2, 15], "x": 204, "y": 31 },
+ { "flags": 4, "matrix": [2, 16], "x": 217, "y": 31 },
+
+ { "flags": 4, "matrix": [3, 0], "x": 11, "y": 41 },
+ { "flags": 4, "matrix": [3, 1], "x": 27, "y": 41 },
+ { "flags": 4, "matrix": [3, 2], "x": 40, "y": 41 },
+ { "flags": 4, "matrix": [3, 3], "x": 52, "y": 41 },
+ { "flags": 4, "matrix": [3, 4], "x": 64, "y": 41 },
+ { "flags": 4, "matrix": [3, 5], "x": 76, "y": 41 },
+ { "flags": 4, "matrix": [3, 6], "x": 88, "y": 41 },
+ { "flags": 4, "matrix": [3, 7], "x": 100, "y": 41 },
+ { "flags": 4, "matrix": [3, 8], "x": 113, "y": 41 },
+ { "flags": 4, "matrix": [3, 9], "x": 124, "y": 41 },
+ { "flags": 4, "matrix": [3, 10], "x": 137, "y": 41 },
+ { "flags": 4, "matrix": [3, 11], "x": 150, "y": 41 },
+ { "flags": 4, "matrix": [3, 13], "x": 170, "y": 41 },
+
+ { "flags": 4, "matrix": [4, 0], "x": 13, "y": 51 },
+ { "flags": 4, "matrix": [4, 2], "x": 34, "y": 51 },
+ { "flags": 4, "matrix": [4, 3], "x": 45, "y": 51 },
+ { "flags": 4, "matrix": [4, 4], "x": 58, "y": 51 },
+ { "flags": 4, "matrix": [4, 5], "x": 70, "y": 51 },
+ { "flags": 4, "matrix": [4, 6], "x": 82, "y": 51 },
+ { "flags": 4, "matrix": [4, 7], "x": 94, "y": 51 },
+ { "flags": 4, "matrix": [4, 8], "x": 107, "y": 51 },
+ { "flags": 4, "matrix": [4, 9], "x": 119, "y": 51 },
+ { "flags": 4, "matrix": [4, 10], "x": 131, "y": 51 },
+ { "flags": 4, "matrix": [4, 11], "x": 143, "y": 51 },
+ { "flags": 4, "matrix": [4, 12], "x": 166, "y": 51 },
+ { "flags": 4, "matrix": [4, 15], "x": 204, "y": 51 },
+
+ { "flags": 4, "matrix": [5, 0], "x": 8, "y": 61 },
+ { "flags": 4, "matrix": [5, 1], "x": 23, "y": 61 },
+ { "flags": 4, "matrix": [5, 2], "x": 38, "y": 61 },
+ { "flags": 4, "matrix": [5, 6], "x": 84, "y": 61 },
+ { "flags": 4, "matrix": [5, 11], "x": 135, "y": 61 },
+ { "flags": 4, "matrix": [5, 12], "x": 152, "y": 61 },
+ { "flags": 4, "matrix": [5, 13], "x": 170, "y": 61 },
+ { "flags": 4, "matrix": [5, 14], "x": 192, "y": 61 },
+ { "flags": 4, "matrix": [5, 15], "x": 204, "y": 61 },
+ { "flags": 4, "matrix": [5, 16], "x": 217, "y": 61 },
+ { "flags": 1, "x": 224, "y": 0 },
+ { "flags": 1, "x": 224, "y": 5 },
+ { "flags": 1, "x": 224, "y": 10 }
+ ]
+ },
"community_layouts": ["tkl_f13_ansi_tsangan"],
"layout_aliases": {
"LAYOUT_all": "LAYOUT_tkl_f13_ansi_tsangan"
diff --git a/keyboards/novelkeys/nk87/keymaps/default/keymap.c b/keyboards/novelkeys/nk87/keymaps/default/keymap.c
index c5ac34e8a39..a6153e213ae 100755
--- a/keyboards/novelkeys/nk87/keymaps/default/keymap.c
+++ b/keyboards/novelkeys/nk87/keymaps/default/keymap.c
@@ -1,34 +1,21 @@
-/* Copyright 2020 Yiancar
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2020 Yiancar
+// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_tkl_f13_ansi_tsangan( /* Base */
- KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_F13, KC_PSCR, KC_SCRL, KC_PAUS,
- KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
- KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
- KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
- KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
- KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
+ KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_F13, KC_PSCR, KC_SCRL, KC_PAUS,
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[1] = LAYOUT_tkl_f13_ansi_tsangan( /* FN */
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, S1_DEC, S1_INC, S2_DEC, S2_INC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, EF_DEC, EF_INC, H1_DEC, H1_INC, H2_DEC, H2_INC, BR_DEC, BR_INC, ES_DEC, ES_INC, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLU, KC_VOLD, KC_MUTE,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, QK_BOOT, _______, _______, _______,
+ _______, RM_TOGG, _______, _______, RM_SATD, RM_SATU, _______, _______, _______, _______, _______, _______, _______,
+ _______, RM_PREV, RM_NEXT, RM_HUED, RM_HUEU, _______, _______, RM_VALD, RM_VALU, RM_SPDD, RM_SPDU, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
};
diff --git a/keyboards/novelkeys/nk87/keymaps/default/readme.md b/keyboards/novelkeys/nk87/keymaps/default/readme.md
deleted file mode 100755
index c0ca4361842..00000000000
--- a/keyboards/novelkeys/nk87/keymaps/default/readme.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# The default keymap for NK87
-
-
-Fn Layer:
-
-
-Default layer is normal ANSI TKL
diff --git a/keyboards/novelkeys/nk87/matrix_diagram.md b/keyboards/novelkeys/nk87/matrix_diagram.md
deleted file mode 100644
index b4d4c3a67aa..00000000000
--- a/keyboards/novelkeys/nk87/matrix_diagram.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Matrix Diagram for NK87
-
-```
-┌───┐┌───┬───┬───┬───┐┌───┬───┬───┬───┐┌───┬───┬───┬───┐┌───┐┌───┬───┬───┐
-│00 ││01 │02 │03 │04 ││05 │06 │07 │08 ││09 │0A │0B │0C ││0D ││0E │0F │0G │
-└───┘└───┴───┴───┴───┘└───┴───┴───┴───┘└───┴───┴───┴───┘└───┘└───┴───┴───┘
-┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐┌───┬───┬───┐
-│10 │11 │12 │13 │14 │15 │16 │17 │18 │19 │1A │1B │1C │1D ││1E │1F │1G │
-├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤├───┼───┼───┤
-│20 │21 │22 │23 │24 │25 │26 │27 │28 │29 │2A │2B │2C │3C ││2E │2F │2G │
-├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤└───┴───┴───┘
-│30 │31 │32 │33 │34 │35 │36 │37 │38 │39 │3A │3B │3D │
-├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐
-│40 │42 │43 │44 │45 │46 │47 │48 │49 │4A │4B │4C │ │4F │
-├─────┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴───┴──┬┴───┴┬───┬─────┤┌───┼───┼───┐
-│50 │51 │52 │56 │5B │5C │5D ││5E │5F │5G │
-└─────┴───┴─────┴───────────────────────────┴─────┴───┴─────┘└───┴───┴───┘
-```
diff --git a/keyboards/novelkeys/nk87/mcuconf.h b/keyboards/novelkeys/nk87/mcuconf.h
index 1aa2fb55b45..886dcd649b5 100644
--- a/keyboards/novelkeys/nk87/mcuconf.h
+++ b/keyboards/novelkeys/nk87/mcuconf.h
@@ -1,43 +1,8 @@
-/* Copyright 2020 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/*
- * This file was auto-generated by:
- * `qmk chibios-confmigrate -i keyboards/nk87/mcuconf.h -r platforms/chibios/QMK_PROTON_C/configs/mcuconf.h`
- */
-
+// Copyright 2020 Yiancar
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include_next
-#undef STM32_GPT_USE_TIM4
-#define STM32_GPT_USE_TIM4 TRUE
-
-#undef STM32_GPT_USE_TIM15
-#define STM32_GPT_USE_TIM15 FALSE
-
-#undef STM32_PWM_USE_TIM3
-#define STM32_PWM_USE_TIM3 FALSE
-
-#undef STM32_PWM_USE_TIM4
-#define STM32_PWM_USE_TIM4 FALSE
-
-#undef STM32_SERIAL_USE_USART2
-#define STM32_SERIAL_USE_USART2 FALSE
-
-#undef STM32_SPI_USE_SPI2
-#define STM32_SPI_USE_SPI2 FALSE
-
+#undef STM32_I2C_USE_I2C1
+#define STM32_I2C_USE_I2C1 TRUE
diff --git a/keyboards/novelkeys/nk87/nk87.c b/keyboards/novelkeys/nk87/nk87.c
index 420141c7283..41b046c0176 100755
--- a/keyboards/novelkeys/nk87/nk87.c
+++ b/keyboards/novelkeys/nk87/nk87.c
@@ -1,26 +1,8 @@
-/* Copyright 2020 Yiancar
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#ifndef RGB_BACKLIGHT_NK87
-#error RGB_BACKLIGHT_NK87 not defined, recheck config.h
-#endif
+// Copyright 2020 Yiancar
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "quantum.h"
-#include "nk87.h"
-#include "drivers/led/issi/is31fl3733.h"
-
-#if defined(RGB_MATRIX_ENABLE) || defined(RGB_BACKLIGHT_NK87)
+#if defined(RGB_MATRIX_ENABLE)
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
@@ -28,171 +10,134 @@ const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
* | | G location
* | | | B location
* | | | | */
+ {1, SW2_CS1, SW1_CS1, SW3_CS1}, //LB1
+ {1, SW2_CS2, SW1_CS2, SW3_CS2}, //LB5
+ {1, SW2_CS3, SW1_CS3, SW3_CS3}, //LB9
+ {1, SW2_CS4, SW1_CS4, SW3_CS4}, //LB13
+ {1, SW2_CS5, SW1_CS5, SW3_CS5}, //LB17
+ {1, SW2_CS6, SW1_CS6, SW3_CS6}, //LB21
+ {1, SW2_CS7, SW1_CS7, SW3_CS7}, //LB25
+ {1, SW2_CS8, SW1_CS8, SW3_CS8}, //LB29
+ {1, SW2_CS9, SW1_CS9, SW3_CS9}, //LB33
+ {1, SW2_CS10, SW1_CS10, SW3_CS10}, //LB37
+ {1, SW2_CS11, SW1_CS11, SW3_CS11}, //LB41
+ {1, SW2_CS12, SW1_CS12, SW3_CS12}, //LB45
+ {1, SW2_CS13, SW1_CS13, SW3_CS13}, //LB49
+ {1, SW2_CS14, SW1_CS14, SW3_CS14}, //LB53
+ {1, SW2_CS15, SW1_CS15, SW3_CS15}, //LB57
+ {1, SW2_CS16, SW1_CS16, SW3_CS16}, //LB61
+ {1, SW11_CS16, SW10_CS16, SW12_CS16}, //LB64
+
{0, SW2_CS1, SW1_CS1, SW3_CS1}, //LA1
- {0, SW5_CS1, SW4_CS1, SW6_CS1}, //LA2
- {0, SW8_CS1, SW7_CS1, SW9_CS1}, //LA3
- {0, SW11_CS1, SW10_CS1, SW12_CS1}, //LA4
{0, SW2_CS2, SW1_CS2, SW3_CS2}, //LA5
- {0, SW5_CS2, SW4_CS2, SW6_CS2}, //LA6
- {0, SW8_CS2, SW7_CS2, SW9_CS2}, //LA7
- {0, SW11_CS2, SW10_CS2, SW12_CS2}, //LA8
{0, SW2_CS3, SW1_CS3, SW3_CS3}, //LA9
- {0, SW5_CS3, SW4_CS3, SW6_CS3}, //LA10
- {0, SW8_CS3, SW7_CS3, SW9_CS3}, //LA11
- {0, SW11_CS3, SW10_CS3, SW12_CS3}, //LA12
{0, SW2_CS4, SW1_CS4, SW3_CS4}, //LA13
- {0, SW5_CS4, SW4_CS4, SW6_CS4}, //LA14
- {0, SW8_CS4, SW7_CS4, SW9_CS4}, //LA15
- {0, SW11_CS4, SW10_CS4, SW12_CS4}, //LA16
{0, SW2_CS5, SW1_CS5, SW3_CS5}, //LA17
- {0, SW5_CS5, SW4_CS5, SW6_CS5}, //LA18
- {0, SW8_CS5, SW7_CS5, SW9_CS5}, //LA19
- {0, SW11_CS5, SW10_CS5, SW12_CS5}, //LA20
{0, SW2_CS6, SW1_CS6, SW3_CS6}, //LA21
- {0, SW5_CS6, SW4_CS6, SW6_CS6}, //LA22
- {0, SW8_CS6, SW7_CS6, SW9_CS6}, //LA23
- {0, SW11_CS6, SW10_CS6, SW12_CS6}, //LA24
{0, SW2_CS7, SW1_CS7, SW3_CS7}, //LA25
- {0, SW5_CS7, SW4_CS7, SW6_CS7}, //LA26
- {0, SW8_CS7, SW7_CS7, SW9_CS7}, //LA27
- {0, SW11_CS7, SW10_CS7, SW12_CS7}, //LA28
{0, SW2_CS8, SW1_CS8, SW3_CS8}, //LA29
- {0, SW5_CS8, SW4_CS8, SW6_CS8}, //LA30
- {0, SW8_CS8, SW7_CS8, SW9_CS8}, //LA31
- {0, SW11_CS8, SW10_CS8, SW12_CS8}, //LA32
{0, SW2_CS9, SW1_CS9, SW3_CS9}, //LA33
- {0, SW5_CS9, SW4_CS9, SW6_CS9}, //LA34
- {0, SW8_CS9, SW7_CS9, SW9_CS9}, //LA35
- {0, SW11_CS9, SW10_CS9, SW12_CS9}, //LA36
{0, SW2_CS10, SW1_CS10, SW3_CS10}, //LA37
- {0, SW5_CS10, SW4_CS10, SW6_CS10}, //LA38
- {0, SW8_CS10, SW7_CS10, SW9_CS10}, //LA39
- {0, SW11_CS10, SW10_CS10, SW12_CS10}, //LA40
{0, SW2_CS11, SW1_CS11, SW3_CS11}, //LA41
- {0, SW5_CS11, SW4_CS11, SW6_CS11}, //LA42
- {0, SW8_CS11, SW7_CS11, SW9_CS11}, //LA43
- {0, SW11_CS11, SW10_CS11, SW12_CS11}, //LA44
{0, SW2_CS12, SW1_CS12, SW3_CS12}, //LA45
- {0, SW5_CS12, SW4_CS12, SW6_CS12}, //LA46
- {0, SW8_CS12, SW7_CS12, SW9_CS12}, //LA47
- {0, SW11_CS12, SW10_CS12, SW12_CS12}, //LA48
{0, SW2_CS13, SW1_CS13, SW3_CS13}, //LA49
- {0, SW5_CS13, SW4_CS13, SW6_CS13}, //LA50
- {0, SW8_CS13, SW7_CS13, SW9_CS13}, //LA51
- {0, SW11_CS13, SW10_CS13, SW12_CS13}, //LA52
{0, SW2_CS14, SW1_CS14, SW3_CS14}, //LA53
+ {1, SW11_CS13, SW10_CS13, SW12_CS13}, //LB52
+ {1, SW11_CS14, SW10_CS14, SW12_CS14}, //LB56
+ {1, SW11_CS15, SW10_CS15, SW12_CS15}, //LB60
+
+ {0, SW5_CS1, SW4_CS1, SW6_CS1}, //LA2
+ {0, SW5_CS2, SW4_CS2, SW6_CS2}, //LA6
+ {0, SW5_CS3, SW4_CS3, SW6_CS3}, //LA10
+ {0, SW5_CS4, SW4_CS4, SW6_CS4}, //LA14
+ {0, SW5_CS5, SW4_CS5, SW6_CS5}, //LA18
+ {0, SW5_CS6, SW4_CS6, SW6_CS6}, //LA22
+ {0, SW5_CS7, SW4_CS7, SW6_CS7}, //LA26
+ {0, SW5_CS8, SW4_CS8, SW6_CS8}, //LA30
+ {0, SW5_CS9, SW4_CS9, SW6_CS9}, //LA34
+ {0, SW5_CS10, SW4_CS10, SW6_CS10}, //LA38
+ {0, SW5_CS11, SW4_CS11, SW6_CS11}, //LA42
+ {0, SW5_CS12, SW4_CS12, SW6_CS12}, //LA46
+ {0, SW5_CS13, SW4_CS13, SW6_CS13}, //LA50
{0, SW5_CS14, SW4_CS14, SW6_CS14}, //LA54
+ {1, SW8_CS13, SW7_CS13, SW9_CS13}, //LB51
+ {1, SW8_CS14, SW7_CS14, SW9_CS14}, //LB55
+ {1, SW8_CS15, SW7_CS15, SW9_CS15}, //LB59
+
+ {0, SW8_CS1, SW7_CS1, SW9_CS1}, //LA3
+ {0, SW8_CS2, SW7_CS2, SW9_CS2}, //LA7
+ {0, SW8_CS3, SW7_CS3, SW9_CS3}, //LA11
+ {0, SW8_CS4, SW7_CS4, SW9_CS4}, //LA15
+ {0, SW8_CS5, SW7_CS5, SW9_CS5}, //LA19
+ {0, SW8_CS6, SW7_CS6, SW9_CS6}, //LA23
+ {0, SW8_CS7, SW7_CS7, SW9_CS7}, //LA27
+ {0, SW8_CS8, SW7_CS8, SW9_CS8}, //LA31
+ {0, SW8_CS9, SW7_CS9, SW9_CS9}, //LA35
+ {0, SW8_CS10, SW7_CS10, SW9_CS10}, //LA39
+ {0, SW8_CS11, SW7_CS11, SW9_CS11}, //LA43
+ {0, SW8_CS12, SW7_CS12, SW9_CS12}, //LA47
{0, SW8_CS14, SW7_CS14, SW9_CS14}, //LA55
- {0, SW11_CS14, SW10_CS14, SW12_CS14}, //LA56
+
+ {0, SW11_CS1, SW10_CS1, SW12_CS1}, //LA4
+ {0, SW11_CS2, SW10_CS2, SW12_CS2}, //LA8
+ {0, SW11_CS3, SW10_CS3, SW12_CS3}, //LA12
+ {0, SW11_CS4, SW10_CS4, SW12_CS4}, //LA16
+ {0, SW11_CS5, SW10_CS5, SW12_CS5}, //LA20
+ {0, SW11_CS6, SW10_CS6, SW12_CS6}, //LA24
+ {0, SW11_CS7, SW10_CS7, SW12_CS7}, //LA28
+ {0, SW11_CS8, SW10_CS8, SW12_CS8}, //LA32
+ {0, SW11_CS9, SW10_CS9, SW12_CS9}, //LA36
+ {0, SW11_CS10, SW10_CS10, SW12_CS10}, //LA40
+ {0, SW11_CS11, SW10_CS11, SW12_CS11}, //LA44
+ {0, SW8_CS13, SW7_CS13, SW9_CS13}, //LA51
+ {0, SW11_CS13, SW10_CS13, SW12_CS13}, //LA52
+
{0, SW2_CS15, SW1_CS15, SW3_CS15}, //LA57
{0, SW5_CS15, SW4_CS15, SW6_CS15}, //LA58
{0, SW8_CS15, SW7_CS15, SW9_CS15}, //LA59
- {0, SW11_CS15, SW10_CS15, SW12_CS15}, //LA60
- {0, SW2_CS16, SW1_CS16, SW3_CS16}, //LA61
+ {0, SW11_CS15, SW10_CS15, SW12_CS15}, //LA60
{0, SW5_CS16, SW4_CS16, SW6_CS16}, //LA62
{0, SW8_CS16, SW7_CS16, SW9_CS16}, //LA63
- {0, SW11_CS16, SW10_CS16, SW12_CS16}, //LA64
+ {0, SW11_CS16, SW10_CS16, SW12_CS16}, //LA64
+ {0, SW11_CS12, SW10_CS12, SW12_CS12}, //LA48
+ {0, SW11_CS14, SW10_CS14, SW12_CS14}, //LA56
+ {1, SW11_CS3, SW10_CS3, SW12_CS3}, //LB12
- {1, SW2_CS1, SW1_CS1, SW3_CS1}, //LB1
- {1, SW5_CS1, SW4_CS1, SW6_CS1}, //LB2
- {1, SW8_CS1, SW7_CS1, SW9_CS1}, //LB3
- {1, SW11_CS1, SW10_CS1, SW12_CS1}, //LB4
- {1, SW2_CS2, SW1_CS2, SW3_CS2}, //LB5
- {1, SW5_CS2, SW4_CS2, SW6_CS2}, //LB6
- {1, SW8_CS2, SW7_CS2, SW9_CS2}, //LB7
- {1, SW11_CS2, SW10_CS2, SW12_CS2}, //LB8
- {1, SW2_CS3, SW1_CS3, SW3_CS3}, //LB9
- {1, SW5_CS3, SW4_CS3, SW6_CS3}, //LB10
- {1, SW8_CS3, SW7_CS3, SW9_CS3}, //LB11
- {1, SW11_CS3, SW10_CS3, SW12_CS3}, //LB12
- {1, SW2_CS4, SW1_CS4, SW3_CS4}, //LB13
- {1, SW5_CS4, SW4_CS4, SW6_CS4}, //LB14
- {1, SW8_CS4, SW7_CS4, SW9_CS4}, //LB15
- {1, SW11_CS4, SW10_CS4, SW12_CS4}, //LB16
- {1, SW2_CS5, SW1_CS5, SW3_CS5}, //LB17
- {1, SW5_CS5, SW4_CS5, SW6_CS5}, //LB18
- {1, SW8_CS5, SW7_CS5, SW9_CS5}, //LB19
- {1, SW11_CS5, SW10_CS5, SW12_CS5}, //LB20
- {1, SW2_CS6, SW1_CS6, SW3_CS6}, //LB21
- {1, SW5_CS6, SW4_CS6, SW6_CS6}, //LB22
- {1, SW8_CS6, SW7_CS6, SW9_CS6}, //LB23
- {1, SW11_CS6, SW10_CS6, SW12_CS6}, //LB24
- {1, SW2_CS7, SW1_CS7, SW3_CS7}, //LB25
- {1, SW5_CS7, SW4_CS7, SW6_CS7}, //LB26
- {1, SW8_CS7, SW7_CS7, SW9_CS7}, //LB27
- {1, SW11_CS7, SW10_CS7, SW12_CS7}, //LB28
- {1, SW2_CS8, SW1_CS8, SW3_CS8}, //LB29
- {1, SW5_CS8, SW4_CS8, SW6_CS8}, //LB30
- {1, SW8_CS8, SW7_CS8, SW9_CS8}, //LB31
- {1, SW11_CS8, SW10_CS8, SW12_CS8}, //LB32
- {1, SW2_CS9, SW1_CS9, SW3_CS9}, //LB33
- {1, SW5_CS9, SW4_CS9, SW6_CS9}, //LB34
- {1, SW8_CS9, SW7_CS9, SW9_CS9}, //LB35
- {1, SW11_CS9, SW10_CS9, SW12_CS9}, //LB36
- {1, SW2_CS10, SW1_CS10, SW3_CS10}, //LB37
- {1, SW5_CS10, SW4_CS10, SW6_CS10}, //LB38
- {1, SW8_CS10, SW7_CS10, SW9_CS10}, //LB39
- {1, SW11_CS10, SW10_CS10, SW12_CS10}, //LB40
- {1, SW2_CS11, SW1_CS11, SW3_CS11}, //LB41
- {1, SW5_CS11, SW4_CS11, SW6_CS11}, //LB42
- {1, SW8_CS11, SW7_CS11, SW9_CS11}, //LB43
- {1, SW11_CS11, SW10_CS11, SW12_CS11}, //LB44
- {1, SW2_CS12, SW1_CS12, SW3_CS12}, //LB45
- {1, SW5_CS12, SW4_CS12, SW6_CS12}, //LB46
- {1, SW8_CS12, SW7_CS12, SW9_CS12}, //LB47
- {1, SW11_CS12, SW10_CS12, SW12_CS12}, //LB48
- {1, SW2_CS13, SW1_CS13, SW3_CS13}, //LB49
- {1, SW5_CS13, SW4_CS13, SW6_CS13}, //LB50
- {1, SW8_CS13, SW7_CS13, SW9_CS13}, //LB51
- {1, SW11_CS13, SW10_CS13, SW12_CS13}, //LB52
- {1, SW2_CS14, SW1_CS14, SW3_CS14}, //LB53
- {1, SW5_CS14, SW4_CS14, SW6_CS14}, //LB54
- {1, SW8_CS14, SW7_CS14, SW9_CS14}, //LB55
- {1, SW11_CS14, SW10_CS14, SW12_CS14}, //LB56
- {1, SW2_CS15, SW1_CS15, SW3_CS15}, //LB57
- {1, SW5_CS15, SW4_CS15, SW6_CS15}, //LB58
- {1, SW8_CS15, SW7_CS15, SW9_CS15}, //LB59
- {1, SW11_CS15, SW10_CS15, SW12_CS15}, //LB60
- {1, SW2_CS16, SW1_CS16, SW3_CS16}, //LB61
- {1, SW5_CS16, SW4_CS16, SW6_CS16}, //LB62
- {1, SW8_CS16, SW7_CS16, SW9_CS16}, //LB63
- {1, SW11_CS16, SW10_CS16, SW12_CS16}, //LB64
+ // Mapped with "dead" locations so each indicator is logically separate
+ {1, SW5_CS16, SW4_CS16, SW9_CS16}, //LB63 - top indi
+ {1, SW8_CS16, SW7_CS16, SW6_CS16}, //LB63 - mid indi
+ {1, SW11_CS12, SW10_CS12, SW12_CS12}, //LB48 - bot indi
};
-#endif
/* Indicator LEDS are part of the LED driver
* Top LED is blue only. LED driver 2 RGB 63 Blue channel
* Middle LED is blue and red. LED driver 2 RGB 63 Red and Green channel
* Bottom LED is red only LED driver 2 RGB 48 Blue channel.
*/
-uint8_t CAPS = 0;
-uint8_t FN1 = 0;
-uint8_t FN2 = 0;
-
-bool led_update_kb(led_t led_state) {
- bool res = led_update_user(led_state);
- if(res) {
- if (led_state.caps_lock) {
- CAPS = 255;
- } else {
- CAPS = 0;
- }
+bool rgb_matrix_indicators_kb(void) {
+ if (!rgb_matrix_indicators_user()) {
+ return false;
}
- is31fl3733_set_color( 63+64-1, FN1, FN1, CAPS );
- is31fl3733_set_color( 48+64-1, 0, 0, FN2 );
- return res;
-}
-__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) {
+ if (host_keyboard_led_state().caps_lock) {
+ rgb_matrix_set_color(87, RGB_WHITE);
+ } else {
+ rgb_matrix_set_color(87, RGB_OFF);
+ }
+
+ layer_state_t state = layer_state|default_layer_state;
if (state & (1UL << 1)) {
- FN1 = 255;
+ rgb_matrix_set_color(88, RGB_WHITE);
} else {
- FN1 = 0;
+ rgb_matrix_set_color(88, RGB_OFF);
}
+
if (state & (1UL << 2)) {
- FN2 = 255;
+ rgb_matrix_set_color(89, RGB_WHITE);
} else {
- FN2 = 0;
+ rgb_matrix_set_color(89, RGB_OFF);
}
- return state;
+
+ return true;
}
+#endif
diff --git a/keyboards/novelkeys/nk87/readme.md b/keyboards/novelkeys/nk87/readme.md
index 0de3e08b401..43d98d6c83d 100755
--- a/keyboards/novelkeys/nk87/readme.md
+++ b/keyboards/novelkeys/nk87/readme.md
@@ -8,27 +8,20 @@ This is a standard fixed layout TKL PCB. It supports VIA and full per-key RGB.
* Hardware Supported: A TKL keyboard with STM32F303CC
* Hardware Availability: https://novelkeys.xyz/
-## Instructions
-
-### Build
-
Make example for this keyboard (after setting up your build environment):
make novelkeys/nk87:default
+Flashing example for this keyboard:
+
+ make novelkeys/nk87:default:flash
+
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
-### Reset
+## Bootloader
-- Unplug
-- Hold Escape
-- Plug In
-- Unplug
-- Release Escape
+Enter the bootloader in 3 ways:
-### Flash
-
-- Unplug
-- Hold Escape
-- Plug In
-- Flash using QMK Toolbox or dfu-util (`make nk87::dfu-util`)
+* **Bootmagic reset**: Hold down the top left key and plug in the keyboard
+* **Physical reset button**: Briefly press the button on the back of the PCB
+* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
diff --git a/keyboards/novelkeys/nk87/rules.mk b/keyboards/novelkeys/nk87/rules.mk
deleted file mode 100755
index 3b7a32713c3..00000000000
--- a/keyboards/novelkeys/nk87/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-# Do not put the microcontroller into power saving mode
-# when we get USB suspend event. We want it to keep updating
-# backlight effects.
-NO_SUSPEND_POWER_DOWN = yes
-
-CIE1931_CURVE = yes
-I2C_DRIVER_REQUIRED = yes
-
-# project specific files
-SRC = keyboards/wilba_tech/wt_main.c \
- keyboards/wilba_tech/wt_rgb_backlight.c \
- drivers/led/issi/is31fl3733.c \
- quantum/color.c
diff --git a/keyboards/planck/light/keyboard.json b/keyboards/planck/light/keyboard.json
index f445cca931d..907dd0c6d5e 100644
--- a/keyboards/planck/light/keyboard.json
+++ b/keyboards/planck/light/keyboard.json
@@ -98,7 +98,7 @@
{"matrix": [3, 3], "x": 61, "y": 63, "flags": 1},
{"matrix": [3, 4], "x": 81, "y": 63, "flags": 1},
{"matrix": [3, 5], "x": 101, "y": 63, "flags": 4},
- {"x": 111, "y": 63, "flags": 4},
+ {"matrix": [3, 5], "x": 111, "y": 63, "flags": 4},
{"matrix": [3, 6], "x": 122, "y": 63, "flags": 4},
{"matrix": [3, 7], "x": 142, "y": 63, "flags": 1},
{"matrix": [3, 8], "x": 162, "y": 63, "flags": 1},
diff --git a/keyboards/planck/light/light.c b/keyboards/planck/light/light.c
index 97ea06c467c..b7dabcd6ced 100644
--- a/keyboards/planck/light/light.c
+++ b/keyboards/planck/light/light.c
@@ -86,16 +86,6 @@ void matrix_init_kb(void) {
matrix_init_user();
}
-uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) {
- // Spacebar has 2 leds 41 & 42, so add 42 to the array here, and 41 will be added
- // by the default lookup code that runs after this
- if (row == 3 && column == 5) {
- led_i[0] = 42;
- return 1;
- }
- return 0;
-}
-
#ifdef SWAP_HANDS_ENABLE
__attribute__ ((weak))
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/rocketboard_16/keycode_lookup.c b/keyboards/rocketboard_16/keycode_lookup.c
index a765968bc3e..1e5bc0a22e9 100644
--- a/keyboards/rocketboard_16/keycode_lookup.c
+++ b/keyboards/rocketboard_16/keycode_lookup.c
@@ -19,7 +19,6 @@
#include "quantum_keycodes.h"
#include "keymap_us.h"
#include "print.h"
-#include "via.h"
#include "util.h"
#define num_keycodes ARRAY_SIZE(lookup_table)
diff --git a/keyboards/sawnsprojects/satxri6key/keyboard.json b/keyboards/sawnsprojects/satxri6key/keyboard.json
index 30f1ec3fd14..100d92325b3 100644
--- a/keyboards/sawnsprojects/satxri6key/keyboard.json
+++ b/keyboards/sawnsprojects/satxri6key/keyboard.json
@@ -92,7 +92,7 @@
"bootmagic": true,
"extrakey": true,
"mousekey": true,
- "nkro": false
+ "rgblight": true
},
"matrix_pins": {
"cols": ["F1", "F4", "F5"],
@@ -101,8 +101,12 @@
"diode_direction": "COL2ROW",
"processor": "atmega32u4",
"bootloader": "atmel-dfu",
+ "community_layouts": ["ortho_2x3"],
+ "layout_aliases": {
+ "LAYOUT": "LAYOUT_ortho_2x3"
+ },
"layouts": {
- "LAYOUT": {
+ "LAYOUT_ortho_2x3": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
diff --git a/keyboards/sawnsprojects/satxri6key/keymaps/default/keymap.c b/keyboards/sawnsprojects/satxri6key/keymaps/default/keymap.c
index b44effb84de..a38b1adfc9c 100644
--- a/keyboards/sawnsprojects/satxri6key/keymaps/default/keymap.c
+++ b/keyboards/sawnsprojects/satxri6key/keymaps/default/keymap.c
@@ -1,34 +1,15 @@
-/* Copyright 2021 SawnsProjects
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
+// Copyright 2021 SawnsProjects
+// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
-
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
- [0] = LAYOUT(
-
+ [0] = LAYOUT_ortho_2x3(
KC_ESC, KC_GRV, TO(1),
- KC_Z, KC_X, KC_C ),
-
- [1] = LAYOUT(
-
- KC_TRNS, KC_TRNS, TO(0),
- KC_TRNS, KC_TRNS, KC_TRNS ),
-
-
+ KC_Z, KC_X, KC_C
+ ),
+ [1] = LAYOUT_ortho_2x3(
+ _______, _______, TO(0),
+ _______, _______, _______
+ )
};
-
diff --git a/keyboards/sawnsprojects/satxri6key/keymaps/default/rules.mk b/keyboards/sawnsprojects/satxri6key/keymaps/default/rules.mk
index 3d821b064a3..1a840036e2a 100644
--- a/keyboards/sawnsprojects/satxri6key/keymaps/default/rules.mk
+++ b/keyboards/sawnsprojects/satxri6key/keymaps/default/rules.mk
@@ -1,4 +1,2 @@
-VIA_ENABLE = no
RGBLIGHT_ENABLE = no
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = ws2812
diff --git a/keyboards/sirius/unigo66/custom_matrix.cpp b/keyboards/sirius/unigo66/custom_matrix.cpp
index 879a0e7c153..122136f1bc9 100644
--- a/keyboards/sirius/unigo66/custom_matrix.cpp
+++ b/keyboards/sirius/unigo66/custom_matrix.cpp
@@ -210,13 +210,15 @@ extern "C"
}
}
- void led_set(uint8_t usb_led)
- {
- kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
- kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
- kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
- kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
- led_update_kb((led_t){.raw = usb_led});
+ bool led_update_kb(led_t led_state) {
+ bool res = led_update_user(led_state);
+ if(res) {
+ kbd1.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ kbd2.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ kbd3.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ kbd4.SetReport(0, 0, 2, 0, 1, &led_state.raw);
+ }
+ return res;
}
};
diff --git a/keyboards/spaceholdings/nebula12/config.h b/keyboards/spaceholdings/nebula12/config.h
index c88b219b09e..141b3afeb9c 100755
--- a/keyboards/spaceholdings/nebula12/config.h
+++ b/keyboards/spaceholdings/nebula12/config.h
@@ -92,6 +92,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/spaceholdings/nebula68/config.h b/keyboards/spaceholdings/nebula68/config.h
index 85d3261dd12..f441fe0aa25 100755
--- a/keyboards/spaceholdings/nebula68/config.h
+++ b/keyboards/spaceholdings/nebula68/config.h
@@ -76,6 +76,4 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 32
+#define EECONFIG_KB_DATA_SIZE 32
diff --git a/keyboards/tkc/portico/config.h b/keyboards/tkc/portico/config.h
index a57c0b4b1d0..93176ee2f8e 100644
--- a/keyboards/tkc/portico/config.h
+++ b/keyboards/tkc/portico/config.h
@@ -70,8 +70,6 @@ along with this program. If not, see .
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_3 0b0111000000000001
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 0b1111111111111111
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
#endif
diff --git a/keyboards/tkc/portico/portico.h b/keyboards/tkc/portico/portico.h
index b93c7f8d3c8..951940f47bf 100644
--- a/keyboards/tkc/portico/portico.h
+++ b/keyboards/tkc/portico/portico.h
@@ -20,5 +20,4 @@ along with this program. If not, see .
#include "quantum.h"
#ifdef RGB_BACKLIGHT_PORTICO
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
#endif
diff --git a/keyboards/tkc/portico75/config.h b/keyboards/tkc/portico75/config.h
index 8d209e37759..10f0d95ddf2 100644
--- a/keyboards/tkc/portico75/config.h
+++ b/keyboards/tkc/portico75/config.h
@@ -75,7 +75,5 @@ along with this program. If not, see .
# define RGB_BACKLIGHT_ALPHAS_MODS_ROW_3 0b0111100000000001
# define RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 0b1111111111111111
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-# define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+# define EECONFIG_KB_DATA_SIZE 31
#endif
diff --git a/keyboards/tkc/portico75/portico75.h b/keyboards/tkc/portico75/portico75.h
index a9c26f4d8bf..ff8e351364d 100644
--- a/keyboards/tkc/portico75/portico75.h
+++ b/keyboards/tkc/portico75/portico75.h
@@ -22,5 +22,4 @@ along with this program. If not, see .
#ifdef RGB_BACKLIGHT_PORTICO75
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
#endif
diff --git a/keyboards/tzarc/djinn/djinn.c b/keyboards/tzarc/djinn/djinn.c
index 9723a31a600..8c16bedc1ca 100644
--- a/keyboards/tzarc/djinn/djinn.c
+++ b/keyboards/tzarc/djinn/djinn.c
@@ -209,9 +209,9 @@ void housekeeping_task_kb(void) {
// Match the backlight to the LCD state
if (is_keyboard_master() && is_backlight_enabled() != peripherals_on) {
if (peripherals_on)
- backlight_enable();
+ backlight_enable_noeeprom();
else
- backlight_disable();
+ backlight_disable_noeeprom();
}
// Draw the UI
diff --git a/keyboards/wilba_tech/rama_works_kara/config.h b/keyboards/wilba_tech/rama_works_kara/config.h
index 8a18f654a09..02b702d3538 100644
--- a/keyboards/wilba_tech/rama_works_kara/config.h
+++ b/keyboards/wilba_tech/rama_works_kara/config.h
@@ -85,6 +85,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_kara/rama_works_kara.h b/keyboards/wilba_tech/rama_works_kara/rama_works_kara.h
index b712f6ccd3a..d597cd61d4b 100644
--- a/keyboards/wilba_tech/rama_works_kara/rama_works_kara.h
+++ b/keyboards/wilba_tech/rama_works_kara/rama_works_kara.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_koyu/config.h b/keyboards/wilba_tech/rama_works_koyu/config.h
index a978189362a..f2b9a98f032 100644
--- a/keyboards/wilba_tech/rama_works_koyu/config.h
+++ b/keyboards/wilba_tech/rama_works_koyu/config.h
@@ -85,6 +85,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_koyu/rama_works_koyu.h b/keyboards/wilba_tech/rama_works_koyu/rama_works_koyu.h
index 297b98f6d1f..a740edd7053 100644
--- a/keyboards/wilba_tech/rama_works_koyu/rama_works_koyu.h
+++ b/keyboards/wilba_tech/rama_works_koyu/rama_works_koyu.h
@@ -18,4 +18,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m10_c/config.h b/keyboards/wilba_tech/rama_works_m10_c/config.h
index f9315e00932..d6a1ffd3c23 100644
--- a/keyboards/wilba_tech/rama_works_m10_c/config.h
+++ b/keyboards/wilba_tech/rama_works_m10_c/config.h
@@ -68,6 +68,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 51
+#define EECONFIG_KB_DATA_SIZE 51
diff --git a/keyboards/wilba_tech/rama_works_m10_c/rama_works_m10_c.h b/keyboards/wilba_tech/rama_works_m10_c/rama_works_m10_c.h
index 24dae9d7d06..a51cddb53bd 100644
--- a/keyboards/wilba_tech/rama_works_m10_c/rama_works_m10_c.h
+++ b/keyboards/wilba_tech/rama_works_m10_c/rama_works_m10_c.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m50_a/config.h b/keyboards/wilba_tech/rama_works_m50_a/config.h
index 706230af3bf..72fb9f60890 100644
--- a/keyboards/wilba_tech/rama_works_m50_a/config.h
+++ b/keyboards/wilba_tech/rama_works_m50_a/config.h
@@ -69,6 +69,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_m50_a/rama_works_m50_a.h b/keyboards/wilba_tech/rama_works_m50_a/rama_works_m50_a.h
index 24dae9d7d06..a51cddb53bd 100644
--- a/keyboards/wilba_tech/rama_works_m50_a/rama_works_m50_a.h
+++ b/keyboards/wilba_tech/rama_works_m50_a/rama_works_m50_a.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m60_a/config.h b/keyboards/wilba_tech/rama_works_m60_a/config.h
index ecd6ba1e917..f19cc40595a 100644
--- a/keyboards/wilba_tech/rama_works_m60_a/config.h
+++ b/keyboards/wilba_tech/rama_works_m60_a/config.h
@@ -85,6 +85,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_m60_a/rama_works_m60_a.h b/keyboards/wilba_tech/rama_works_m60_a/rama_works_m60_a.h
index 3966f822ee4..84e2ac0ee6c 100644
--- a/keyboards/wilba_tech/rama_works_m60_a/rama_works_m60_a.h
+++ b/keyboards/wilba_tech/rama_works_m60_a/rama_works_m60_a.h
@@ -17,4 +17,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m65_b/config.h b/keyboards/wilba_tech/rama_works_m65_b/config.h
index e8820868aa1..b6340b4c06e 100644
--- a/keyboards/wilba_tech/rama_works_m65_b/config.h
+++ b/keyboards/wilba_tech/rama_works_m65_b/config.h
@@ -69,6 +69,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_m65_b/rama_works_m65_b.h b/keyboards/wilba_tech/rama_works_m65_b/rama_works_m65_b.h
index 537457a47ed..16ceee46a75 100644
--- a/keyboards/wilba_tech/rama_works_m65_b/rama_works_m65_b.h
+++ b/keyboards/wilba_tech/rama_works_m65_b/rama_works_m65_b.h
@@ -18,4 +18,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m65_bx/config.h b/keyboards/wilba_tech/rama_works_m65_bx/config.h
index e40a4987aac..2e7f42e16c4 100644
--- a/keyboards/wilba_tech/rama_works_m65_bx/config.h
+++ b/keyboards/wilba_tech/rama_works_m65_bx/config.h
@@ -69,6 +69,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_m65_bx/rama_works_m65_bx.h b/keyboards/wilba_tech/rama_works_m65_bx/rama_works_m65_bx.h
index 537457a47ed..16ceee46a75 100644
--- a/keyboards/wilba_tech/rama_works_m65_bx/rama_works_m65_bx.h
+++ b/keyboards/wilba_tech/rama_works_m65_bx/rama_works_m65_bx.h
@@ -18,4 +18,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/rama_works_m6_a/config.h b/keyboards/wilba_tech/rama_works_m6_a/config.h
index f74e6c53892..6d5e422121a 100644
--- a/keyboards/wilba_tech/rama_works_m6_a/config.h
+++ b/keyboards/wilba_tech/rama_works_m6_a/config.h
@@ -20,6 +20,4 @@
// NOTE: M6-A doesn't use RGB backlight, but we keep this
// consistent with M6-B which does.
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 43
+#define EECONFIG_KB_DATA_SIZE 43
diff --git a/keyboards/wilba_tech/rama_works_m6_b/config.h b/keyboards/wilba_tech/rama_works_m6_b/config.h
index 2395700561d..13c7777b906 100644
--- a/keyboards/wilba_tech/rama_works_m6_b/config.h
+++ b/keyboards/wilba_tech/rama_works_m6_b/config.h
@@ -65,6 +65,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 43
+#define EECONFIG_KB_DATA_SIZE 43
diff --git a/keyboards/wilba_tech/rama_works_u80_a/config.h b/keyboards/wilba_tech/rama_works_u80_a/config.h
index 606d2ce3865..febdb0b1a5c 100644
--- a/keyboards/wilba_tech/rama_works_u80_a/config.h
+++ b/keyboards/wilba_tech/rama_works_u80_a/config.h
@@ -87,6 +87,4 @@
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
-// Backlight config starts after VIA's EEPROM usage,
-// dynamic keymaps start after this.
-#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 31
+#define EECONFIG_KB_DATA_SIZE 31
diff --git a/keyboards/wilba_tech/rama_works_u80_a/rama_works_u80_a.h b/keyboards/wilba_tech/rama_works_u80_a/rama_works_u80_a.h
index 297b98f6d1f..a740edd7053 100644
--- a/keyboards/wilba_tech/rama_works_u80_a/rama_works_u80_a.h
+++ b/keyboards/wilba_tech/rama_works_u80_a/rama_works_u80_a.h
@@ -18,4 +18,3 @@
#include "quantum.h"
#include "keyboards/wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
diff --git a/keyboards/wilba_tech/via_test.c b/keyboards/wilba_tech/via_test.c
deleted file mode 100644
index 46cc42a9e40..00000000000
--- a/keyboards/wilba_tech/via_test.c
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2022 Jason Williams (@wilba)
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-// This is a test harness for VIA custom UI.
-//
-// It handles channel IDs 0-7, value IDs 0-7.
-//
-// It's useful for testing custom UI on a PCB without compiling in
-// features, especially features that will cause firmware to freeze
-// if the PCB doesn't have support.
-//
-// To use:
-// - add `SRC = keyboards/wilba_tech/via_test.c` to rules.mk
-// - add `#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 128` to config.h
-// (or change to match CHANNELS*VALUES*2)
-
-#include "via.h"
-
-#ifdef VIA_ENABLE
-
-#define CHANNELS 8
-#define VALUES 8
-uint8_t g_value[CHANNELS][VALUES][2];
-
-void values_init(void)
-{
- for ( uint8_t channel_id = 0; channel_id < CHANNELS; channel_id++ ) {
- for ( uint8_t value_id = 0; value_id < VALUES; value_id++ ) {
- g_value[channel_id][value_id][0] = 0x00;
- g_value[channel_id][value_id][1] = 0x00;
- }
- }
-}
-
-void values_load(void)
-{
- eeprom_read_block( g_value, ((void*)VIA_EEPROM_CUSTOM_CONFIG_ADDR), VIA_EEPROM_CUSTOM_CONFIG_SIZE );
-}
-
-void values_save(void)
-{
- eeprom_update_block( g_value, ((void*)VIA_EEPROM_CUSTOM_CONFIG_ADDR), VIA_EEPROM_CUSTOM_CONFIG_SIZE );
-}
-
-// We do this to test if VIA is sending save commands per channel
-// Not relevant for real situations
-void values_save_on_channel(uint8_t channel_id)
-{
- uint16_t offset = channel_id * VALUES * 2;
- eeprom_update_block( ((void*)g_value) + offset,
- ((void*)VIA_EEPROM_CUSTOM_CONFIG_ADDR) + offset,
- VALUES * 2 );
-}
-
-void via_init_kb(void)
-{
- values_init();
-
- // If the EEPROM has the magic, the data is good.
- // OK to load from EEPROM
- if (via_eeprom_is_valid()) {
- values_load();
- } else {
- values_save();
- // DO NOT set EEPROM valid here, let caller do this
- }
-}
-
-void set_value( uint8_t channel_id, uint8_t *data )
-{
- // data = [ value_id, value_data ]
- uint8_t *value_id = &(data[0]);
- uint8_t *value_data = &(data[1]);
- if ( *value_id >= 0 && *value_id < VALUES ) {
- g_value[channel_id][*value_id][0] = value_data[0];
- g_value[channel_id][*value_id][1] = value_data[1];
- }
-}
-
-void get_value( uint8_t channel_id, uint8_t *data )
-{
- // data = [ value_id, value_data ]
- uint8_t *value_id = &(data[0]);
- uint8_t *value_data = &(data[1]);
- if ( *value_id >= 0 && *value_id < VALUES ) {
- value_data[0] = g_value[channel_id][*value_id][0];
- value_data[1] = g_value[channel_id][*value_id][1];
- }
-}
-
-void via_custom_value_command(uint8_t *data, uint8_t length) {
- // data = [ command_id, channel_id, value_id, value_data ]
- uint8_t *command_id = &(data[0]);
- uint8_t *channel_id = &(data[1]);
- uint8_t *value_id_and_data = &(data[2]);
-
- if ( *channel_id >= 0 && *channel_id < CHANNELS ) {
- switch ( *command_id )
- {
- case id_custom_set_value:
- {
- set_value(*channel_id,value_id_and_data);
- break;
- }
- case id_custom_get_value:
- {
- get_value(*channel_id,value_id_and_data);
- break;
- }
- case id_custom_save:
- {
- //for ( uint8_t i=0; i
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include QMK_KEYBOARD_H
+
+// clang-format off
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = LAYOUT_60_ansi_tsangan_split_bs_rshift(
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(1),
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL
+ ),
+
+ [1] = LAYOUT_60_ansi_tsangan_split_bs_rshift(
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, QK_BOOT,
+ _______, _______, RM_TOGG, RM_VALU, RM_SPDU, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, RM_VALD, RM_SPDD, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______
+ ),
+};
+
+// clang-format on
diff --git a/keyboards/ymdk/oni_tsangan/readme.md b/keyboards/ymdk/oni_tsangan/readme.md
new file mode 100644
index 00000000000..c7fe806a208
--- /dev/null
+++ b/keyboards/ymdk/oni_tsangan/readme.md
@@ -0,0 +1,27 @@
+# YMDK ONI Tsangan
+
+
+
+Customizable 60% Tsangan/HHKB-like Hotswap PCB by [YMDK](https://ymdkey.com).
+
+- Keyboard Maintainer: [chrisgve](https://github.com/chrisgve)
+- Hardware Supported: YMDK ONI Tsangan/HHKB-like
+- Hardware Availability: [YMDK ONI Tsangan/HHKB-like](https://ymdkey.com/products/ymdk-gh60-hhkb-style-tsangan-oni-hot-swappable-both-underglow-switch-rgb-via-programmable-pcb-compatible-with-tokyo-60)
+
+Make example for this keyboard (after setting up your build environment):
+
+ make ymdk/oni_tsangan:default
+
+The keyboard uses a DFU bootloader. To make a keymap and use dfu to flash it:
+
+ make ymdk/oni_tsangan:default:flash
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+
+## Bootloader
+
+Enter the bootloader in 3 ways:
+
+- **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
+- **Physical reset button**: Short the two pads close to the position of the caps lock key
+- **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
diff --git a/lib/python/kle2xy.py b/lib/python/kle2xy.py
index 608d1b98090..0a9476be93c 100644
--- a/lib/python/kle2xy.py
+++ b/lib/python/kle2xy.py
@@ -46,7 +46,7 @@ class KLE2xy(list):
if 'name' in properties:
self.name = properties['name']
- def parse_layout(self, layout): # noqa FIXME(skullydazed): flake8 says this has a complexity of 25, it should be refactored.
+ def parse_layout(self, layout): # noqa: C901 flake8 says this has a complexity of 25, it should be refactored.
# Wrap this in a dictionary so hjson will parse KLE raw data
layout = '{"layout": [' + layout + ']}'
layout = hjson.loads(layout)['layout']
@@ -60,7 +60,7 @@ class KLE2xy(list):
self.attrs(layout[0])
layout = layout[1:]
- for row_num, row in enumerate(layout):
+ for _row_num, row in enumerate(layout):
self.append([])
# Process the current row
diff --git a/lib/python/qmk/cli/bux.py b/lib/python/qmk/cli/bux.py
index 669521d08ef..6fb1df56afe 100755
--- a/lib/python/qmk/cli/bux.py
+++ b/lib/python/qmk/cli/bux.py
@@ -2,14 +2,14 @@
World domination secret weapon.
"""
+
from milc import cli
from milc.subcommand import config
@cli.subcommand('QMK Bux miner.', hidden=True)
def bux(cli):
- """QMK bux
- """
+ """QMK bux"""
if not cli.config.user.bux:
bux = 0
else:
@@ -45,5 +45,5 @@ def bux(cli):
@B r@= :@@- _@@_R@fB#}@@ 2@@@# 8@@#@Q.*@B `@@- y@@N @H B@
@B `. g@9=_~D@g R@}`&@@@ 2@&__` 8@u_Q@2!@@^-x@@` Y@QD@z .` B@
@@BBBBBBBBBBBBBBBBBBB_ `c8@@@81` S#] `N#B l####v D###BA. vg@@#0~ i#&' 5#K RBBBBBBBBBBBBBBBBBB@@
-""" # noqa: Do not care about the ASCII art
+"""
print(f"{buck}\nYou've been blessed by the QMK gods!\nYou have {cli.config.user.bux} QMK bux.")
diff --git a/lib/python/qmk/cli/find.py b/lib/python/qmk/cli/find.py
index 7d8b1b066c9..b0d969ac28e 100644
--- a/lib/python/qmk/cli/find.py
+++ b/lib/python/qmk/cli/find.py
@@ -1,26 +1,17 @@
-"""Command to search through all keyboards and keymaps for a given search criteria.
-"""
+"""Command to search through all keyboards and keymaps for a given search criteria."""
+
import os
from milc import cli
from qmk.search import filter_help, search_keymap_targets
from qmk.util import maybe_exit_config
-@cli.argument(
- '-f',
- '--filter',
- arg_only=True,
- action='append',
- default=[],
- help= # noqa: `format-python` and `pytest` don't agree here.
- f"Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight=true'. Valid functions are {filter_help()}. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'." # noqa: `format-python` and `pytest` don't agree here.
-)
+@cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help=f"Filter the list of keyboards based on their info.json data. Accepts the formats key==value, function(key), or function(key,value), eg. 'features.rgblight==true'. Valid functions are {filter_help()}. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'.") # fmt: off
@cli.argument('-p', '--print', arg_only=True, action='append', default=[], help="For each matched target, print the value of the supplied info.json key. May be passed multiple times.")
@cli.argument('-km', '--keymap', type=str, default='default', help="The keymap name to build. Default is 'default'.")
@cli.subcommand('Find builds which match supplied search criteria.')
def find(cli):
- """Search through all keyboards and keymaps for a given search criteria.
- """
+ """Search through all keyboards and keymaps for a given search criteria."""
os.environ.setdefault('SKIP_SCHEMA_VALIDATION', '1')
maybe_exit_config(should_exit=False, should_reraise=True)
diff --git a/lib/python/qmk/cli/generate/community_modules.py b/lib/python/qmk/cli/generate/community_modules.py
index 22bb7c0a130..845a0c2a09a 100644
--- a/lib/python/qmk/cli/generate/community_modules.py
+++ b/lib/python/qmk/cli/generate/community_modules.py
@@ -169,10 +169,154 @@ def _generate_modules_rules(keyboard, filename):
return lines
+def _module_slugs(modules):
+ return [Path(m).name.lower() for m in modules]
+
+
+def _render_eeconfig_declarations(modules):
+ lines = []
+ lines.append('')
+ lines.append('// nvm eeconfig')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f'bool eeconfig_is_{module_slug}_datablock_valid(void);',
+ f'uint32_t eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));',
+ f'uint32_t eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));',
+ f'void eeconfig_init_{module_slug}_datablock(void);',
+ f'# define eeconfig_read_{module_slug}_datablock_field(__object, __field) eeconfig_read_{module_slug}_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))',
+ f'# define eeconfig_update_{module_slug}_datablock_field(__object, __field) eeconfig_update_{module_slug}_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))',
+ '',
+ f'bool nvm_eeconfig_is_{module_slug}_datablock_valid(void);',
+ f'uint32_t nvm_eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length);',
+ f'uint32_t nvm_eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length);',
+ f'void nvm_eeconfig_init_{module_slug}_datablock(void);',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ '',
+ ])
+
+ lines.append('typedef struct PACKED {')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f' uint32_t {module_slug}_version;',
+ f' uint8_t {module_slug}[EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE];',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ ])
+ lines.append('} eeprom_modules_t;')
+ lines.append('')
+
+ for module_slug in _module_slugs(modules):
+ lines.append(f'#define EECONFIG_MODULE_{module_slug.upper()}_VERSION (uint32_t *)(EECONFIG_MODULES_DATABLOCK + (offsetof(eeprom_modules_t, {module_slug}_version)))')
+ lines.append(f'#define EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK (uint8_t *)(EECONFIG_MODULES_DATABLOCK + (offsetof(eeprom_modules_t, {module_slug})))')
+ lines.append('')
+
+ lines.append('bool eeconfig_is_modules_datablock_valid(void);')
+ lines.append('void eeconfig_init_modules_datablock(void);')
+ lines.append('void eeconfig_prepare_modules_datablocks(void);')
+ lines.append('')
+
+ return lines
+
+
+def _render_eeconfig_implementation(modules):
+ lines = []
+
+ lines.append('')
+ lines.append('// nvm eeconfig')
+ lines.append('#if defined(NVM_DRIVER_EEPROM)')
+ lines.append('# include "nvm_eeprom_eeconfig_internal.h"')
+ lines.append('# include "eeprom.h"')
+ lines.append('#endif // defined(NVM_DRIVER_EEPROM)')
+ lines.append('')
+
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f'bool eeconfig_is_{module_slug}_datablock_valid(void) {{ return nvm_eeconfig_is_{module_slug}_datablock_valid(); }}',
+ f'uint32_t eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) {{ return nvm_eeconfig_read_{module_slug}_datablock(data, offset, length); }}',
+ f'uint32_t eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) {{ return nvm_eeconfig_update_{module_slug}_datablock(data, offset, length); }}',
+ f'__attribute__((weak)) void eeconfig_init_{module_slug}_datablock(void) {{ nvm_eeconfig_init_{module_slug}_datablock(); }}',
+ '',
+ '# if defined(NVM_DRIVER_EEPROM)',
+ f'bool nvm_eeconfig_is_{module_slug}_datablock_valid(void) {{',
+ f' return eeprom_read_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION) == (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION);',
+ '}',
+ f'uint32_t nvm_eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) {{',
+ f' if (eeconfig_is_{module_slug}_datablock_valid()) {{',
+ f' void *ee_start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + offset);',
+ f' void *ee_end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + MIN((EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE), offset + length));',
+ ' eeprom_read_block(data, ee_start, ee_end - ee_start);',
+ ' return ee_end - ee_start;',
+ ' } else {',
+ ' memset(data, 0, length);',
+ ' return length;',
+ ' }',
+ '}',
+ f'uint32_t nvm_eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) {{',
+ f' eeprom_update_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION, (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION));',
+ f' void *ee_start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + offset);',
+ f' void *ee_end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + MIN((EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE), offset + length));',
+ ' eeprom_update_block(data, ee_start, ee_end - ee_start);',
+ ' return ee_end - ee_start;',
+ '}',
+ f'void nvm_eeconfig_init_{module_slug}_datablock(void) {{',
+ f' eeprom_update_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION, (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION));',
+ f' void *start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK);',
+ f' void *end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE));',
+ ' long remaining = end - start;',
+ ' uint8_t dummy[16] = {0};',
+ f' for (int i = 0; i < EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE; i += sizeof(dummy)) {{',
+ ' int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy);',
+ ' eeprom_update_block(dummy, start, this_loop);',
+ ' start += this_loop;',
+ ' remaining -= this_loop;',
+ ' }',
+ '}',
+ '# endif // defined(NVM_DRIVER_EEPROM)',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ '',
+ ])
+
+ lines.append('bool eeconfig_is_modules_datablock_valid(void) {')
+ lines.append(' return true')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f' && eeconfig_is_{module_slug}_datablock_valid()',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ ])
+ lines.append(' ;')
+ lines.append('}')
+ lines.append('')
+
+ lines.append('void eeconfig_init_modules_datablock(void) {')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f' eeconfig_init_{module_slug}_datablock();',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ ])
+ lines.append('}')
+ lines.append('')
+
+ lines.append('void eeconfig_prepare_modules_datablocks(void) {')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ f' if (!eeconfig_is_{module_slug}_datablock_valid()) {{ eeconfig_init_{module_slug}_datablock(); }}',
+ f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
+ ])
+ lines.append('}')
+ lines.append('')
+
+ return lines
+
+
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate rules.mk for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate rules.mk for.')
@cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.')
@cli.subcommand('Creates a community_modules_rules_mk from a keymap.json file.')
def generate_community_modules_rules_mk(cli):
@@ -196,11 +340,11 @@ def generate_community_modules_rules_mk(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_config.h for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_post_config.h for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
-@cli.subcommand('Creates a community_config.h from a keymap.json file.')
-def generate_community_config_h(cli):
- """Creates a community_config.h from a keymap.json file
+@cli.subcommand('Creates a community_post_config.h from a keymap.json file.')
+def generate_community_post_config_h(cli):
+ """Creates a community_post_config.h from a keymap.json file
"""
if cli.args.output and cli.args.output.name == '-':
cli.args.output = None
@@ -215,20 +359,38 @@ def generate_community_config_h(cli):
modules = get_modules(cli.args.keyboard, cli.args.filename)
if len(modules) > 0:
lines.append('// Split transactions')
- for module in modules:
+ for module_slug in _module_slugs(modules):
lines.extend([
- f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{Path(module).name.upper()}',
+ f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{module_slug.upper()}',
'# define SPLIT_TRANSACTION_RPC',
'#endif',
])
lines.append('')
+ lines.append('// nvm eeconfig')
+ for module_slug in _module_slugs(modules):
+ lines.extend([
+ f'#ifndef EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE',
+ f'# define EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE 0',
+ f'# define EECONFIG_MODULE_{module_slug.upper()}_TOTAL_SIZE 0',
+ '#else',
+ f'# define EECONFIG_MODULE_{module_slug.upper()}_TOTAL_SIZE ((EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) + 4)',
+ '#endif',
+ f'#ifndef EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION',
+ f'# define EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE)',
+ '#endif',
+ '',
+ ])
+ module_size = " + ".join([f'(EECONFIG_MODULE_{module_slug.upper()}_TOTAL_SIZE)' for module_slug in _module_slugs(modules)])
+ lines.append(f'#define EECONFIG_MODULE_DATA_SIZE ({module_size})')
+ lines.append('')
+
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.h for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.h for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates a community_modules.h from a keymap.json file.')
def generate_community_modules_h(cli):
@@ -245,6 +407,7 @@ def generate_community_modules_h(cli):
'#pragma once',
'#include ',
'#include ',
+ '#include ',
'#include ',
'',
'#include "compiler_support.h"',
@@ -272,6 +435,8 @@ def generate_community_modules_h(cli):
lines.extend(_render_api_declarations(api, Path(module).name))
lines.append('')
+ lines.extend(_render_eeconfig_declarations(modules))
+
lines.append('// Core wrapper')
for api in api_list:
lines.extend(_render_api_declarations(api, 'modules', user_kb=False))
@@ -281,7 +446,7 @@ def generate_community_modules_h(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates a community_modules.c from a keymap.json file.')
def generate_community_modules_c(cli):
@@ -309,6 +474,8 @@ def generate_community_modules_c(cli):
for api in api_list:
lines.extend(_render_core_implementation(api, modules))
+ lines.extend(_render_eeconfig_implementation(modules))
+
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
@@ -331,7 +498,7 @@ def _generate_include_per_module(cli, include_file_name):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules_introspection.h for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules_introspection.h for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates a community_modules_introspection.h from a keymap.json file.')
def generate_community_modules_introspection_h(cli):
@@ -342,7 +509,7 @@ def generate_community_modules_introspection_h(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates a community_modules_introspection.c from a keymap.json file.')
def generate_community_modules_introspection_c(cli):
@@ -353,7 +520,7 @@ def generate_community_modules_introspection_c(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate led_matrix_community_modules.inc for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate led_matrix_community_modules.inc for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates an led_matrix_community_modules.inc from a keymap.json file.')
def generate_led_matrix_community_modules_inc(cli):
@@ -364,7 +531,7 @@ def generate_led_matrix_community_modules_inc(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate rgb_matrix_community_modules.inc for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate rgb_matrix_community_modules.inc for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates an rgb_matrix_community_modules.inc from a keymap.json file.')
def generate_rgb_matrix_community_modules_inc(cli):
@@ -375,7 +542,7 @@ def generate_rgb_matrix_community_modules_inc(cli):
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate split_transaction_id_community_modules.inc for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate split_transaction_id_community_modules.inc for.')
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
@cli.subcommand('Creates an split_transaction_id_community_modules.inc from a keymap.json file.')
def generate_split_transaction_id_community_modules_inc(cli):
diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py
index 4fd628f0168..8e2ada4f8aa 100755
--- a/lib/python/qmk/cli/generate/config_h.py
+++ b/lib/python/qmk/cli/generate/config_h.py
@@ -170,6 +170,18 @@ def generate_led_animations_config(feature, led_feature_json, config_h_lines, en
config_h_lines.append(generate_flag(f'{enable_prefix}{animation.upper()}', led_feature_json['animations'][animation]))
+def generate_stenography_config(kb_info_json, config_h_lines):
+ """Generate the config.h lines for stenography."""
+ if 'mode' in kb_info_json['stenography'].get('default', {}):
+ mode_map = {
+ 'geminipr': 'STENO_MODE_GEMINI',
+ 'txbolt': 'STENO_MODE_BOLT',
+ }
+ mode = kb_info_json['stenography']['default']['mode']
+ value = mode_map.get(mode, f'STENO_MODE_{mode.upper()}')
+ config_h_lines.append(generate_define('STENO_DEFAULT_MODE', value))
+
+
@cli.argument('filename', nargs='?', arg_only=True, type=FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.')
@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@@ -214,5 +226,8 @@ def generate_config_h(cli):
if 'rgblight' in kb_info_json:
generate_led_animations_config('rgblight', kb_info_json['rgblight'], config_h_lines, 'RGBLIGHT_EFFECT_', 'RGBLIGHT_MODE_')
+ if 'stenography' in kb_info_json:
+ generate_stenography_config(kb_info_json, config_h_lines)
+
# Show the results
dump_lines(cli.args.output, config_h_lines, cli.args.quiet)
diff --git a/lib/python/qmk/cli/generate/develop_pr_list.py b/lib/python/qmk/cli/generate/develop_pr_list.py
index 549db5b185f..9bbe2099302 100755
--- a/lib/python/qmk/cli/generate/develop_pr_list.py
+++ b/lib/python/qmk/cli/generate/develop_pr_list.py
@@ -39,7 +39,12 @@ def _try_open_cache(cli):
return None
cache_loc = Path(cli.config_file).parent
- return SqliteCache(cache_loc)
+ cache = SqliteCache(cache_loc)
+
+ if cli.args.clean:
+ cache.clear()
+
+ return cache
def _get_github():
@@ -48,9 +53,11 @@ def _get_github():
except ImportError:
return None
- return GhApi()
+ # ghapi v2 (July 2026) is now async by default - luckily v1 happily ignores the sync argument
+ return GhApi(sync=True)
+@cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove cache before list generation.")
@cli.argument('-f', '--from-ref', default='0.11.0', help='Git revision/tag/reference/branch to begin search')
@cli.argument('-b', '--branch', default='upstream/develop', help='Git branch to iterate (default: "upstream/develop")')
@cli.subcommand('Creates the develop PR list.', hidden=False if cli.config.user.developer else True)
diff --git a/lib/python/qmk/cli/generate/dfu_header.py b/lib/python/qmk/cli/generate/dfu_header.py
index aa0252ca86e..eaeb325f53e 100644
--- a/lib/python/qmk/cli/generate/dfu_header.py
+++ b/lib/python/qmk/cli/generate/dfu_header.py
@@ -5,32 +5,22 @@ from milc import cli
from qmk.decorators import automagic_keyboard
from qmk.info import info_json
-from qmk.path import is_keyboard, normpath
-from qmk.keyboard import keyboard_completer
+from qmk.path import normpath
+from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.commands import dump_lines
from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE
@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='Keyboard to generate LUFA Keyboard.h for.')
+@cli.argument('-kb', '--keyboard', required=True, arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate LUFA Keyboard.h for.')
@cli.subcommand('Used by the make system to generate LUFA Keyboard.h from info.json', hidden=True)
@automagic_keyboard
def generate_dfu_header(cli):
"""Generates the Keyboard.h file.
"""
- # Determine our keyboard(s)
- if not cli.config.generate_dfu_header.keyboard:
- cli.log.error('Missing parameter: --keyboard')
- cli.subcommands['info'].print_help()
- return False
-
- if not is_keyboard(cli.config.generate_dfu_header.keyboard):
- cli.log.error('Invalid keyboard: "%s"', cli.config.generate_dfu_header.keyboard)
- return False
-
# Build the Keyboard.h file.
- kb_info_json = dotty(info_json(cli.config.generate_dfu_header.keyboard))
+ kb_info_json = dotty(info_json(cli.args.keyboard))
keyboard_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once']
keyboard_h_lines.append(f'#define MANUFACTURER "{kb_info_json["manufacturer"]}"')
diff --git a/lib/python/qmk/cli/generate/info_json.py b/lib/python/qmk/cli/generate/info_json.py
index 08c294146bc..7851529e215 100755
--- a/lib/python/qmk/cli/generate/info_json.py
+++ b/lib/python/qmk/cli/generate/info_json.py
@@ -14,7 +14,7 @@ from qmk.info import info_json
from qmk.json_encoders import InfoJSONEncoder
from qmk.json_schema import compile_schema_store
from qmk.keyboard import keyboard_completer, keyboard_folder
-from qmk.path import is_keyboard, normpath
+from qmk.path import normpath
def pruning_validator(validator_class):
@@ -45,7 +45,7 @@ def strip_info_json(kb_info_json):
return validator(kb_info_json)
-@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.')
+@cli.argument('-kb', '--keyboard', required=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.')
@cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.')
@cli.argument('-o', '--output', arg_only=True, completer=FilesCompleter, help='Write the output the specified file, overwriting if necessary.')
@cli.argument('-ow', '--overwrite', arg_only=True, action='store_true', help='Overwrite the existing info.json. (Overrides the location of --output)')
@@ -55,18 +55,8 @@ def strip_info_json(kb_info_json):
def generate_info_json(cli):
"""Generate an info.json file for a keyboard
"""
- # Determine our keyboard(s)
- if not cli.config.generate_info_json.keyboard:
- cli.log.error('Missing parameter: --keyboard')
- cli.subcommands['info'].print_help()
- return False
-
- if not is_keyboard(cli.config.generate_info_json.keyboard):
- cli.log.error('Invalid keyboard: "%s"', cli.config.generate_info_json.keyboard)
- return False
-
if cli.args.overwrite:
- output_path = (Path('keyboards') / cli.config.generate_info_json.keyboard / 'info.json').resolve()
+ output_path = (Path('keyboards') / cli.args.keyboard / 'info.json').resolve()
if cli.args.output:
cli.log.warning('Overwriting user supplied --output with %s', output_path)
@@ -74,7 +64,7 @@ def generate_info_json(cli):
cli.args.output = output_path
# Build the info.json file
- kb_info_json = info_json(cli.config.generate_info_json.keyboard)
+ kb_info_json = info_json(cli.args.keyboard)
strip_info_json(kb_info_json)
info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder, sort_keys=True)
diff --git a/lib/python/qmk/cli/generate/keyboard_c.py b/lib/python/qmk/cli/generate/keyboard_c.py
index 1978de4a22c..010a11cc1f5 100755
--- a/lib/python/qmk/cli/generate/keyboard_c.py
+++ b/lib/python/qmk/cli/generate/keyboard_c.py
@@ -17,10 +17,22 @@ def _gen_led_configs(info_data):
lines = []
if 'layout' in info_data.get('rgb_matrix', {}):
+ lines.append('#ifdef RGB_MATRIX_ENABLE')
+ lines.append('#include "rgb_matrix.h"')
+ lines.append('')
lines.extend(_gen_led_config(info_data, 'rgb_matrix'))
+ lines.extend(_gen_led_duplicate_config(info_data, 'rgb_matrix'))
+ lines.append('#endif')
+ lines.append('')
if 'layout' in info_data.get('led_matrix', {}):
+ lines.append('#ifdef LED_MATRIX_ENABLE')
+ lines.append('#include "led_matrix.h"')
+ lines.append('')
lines.extend(_gen_led_config(info_data, 'led_matrix'))
+ lines.extend(_gen_led_duplicate_config(info_data, 'led_matrix'))
+ lines.append('#endif')
+ lines.append('')
return lines
@@ -45,13 +57,6 @@ def _gen_led_config(info_data, config_type):
pos.append(f'{{{led_data.get("x", 0)}, {led_data.get("y", 0)}}}')
flags.append(str(led_data.get('flags', 0)))
- if config_type == 'rgb_matrix':
- lines.append('#ifdef RGB_MATRIX_ENABLE')
- lines.append('#include "rgb_matrix.h"')
- elif config_type == 'led_matrix':
- lines.append('#ifdef LED_MATRIX_ENABLE')
- lines.append('#include "led_matrix.h"')
-
lines.append('__attribute__ ((weak)) led_config_t g_led_config = {')
lines.append(' {')
for line in matrix:
@@ -60,7 +65,51 @@ def _gen_led_config(info_data, config_type):
lines.append(f' {{ {", ".join(pos)} }},')
lines.append(f' {{ {", ".join(flags)} }},')
lines.append('};')
- lines.append('#endif')
+ lines.append('')
+
+ return lines
+
+
+def _gen_led_duplicate_config(info_data, config_type):
+ """Convert duplicate led mappings to map_row_column_to_led_kb implementations"""
+
+ # precompute our map of matrix[r,c] -> [ids]
+ duplicates = False
+ led_map = {}
+ led_layout = info_data[config_type]['layout']
+ for led_index, led_data in enumerate(led_layout):
+ if 'matrix' in led_data:
+ matrix = tuple(led_data['matrix'])
+ led_map[matrix] = [*led_map.get(matrix, []), led_index]
+ duplicates = True
+
+ if not duplicates:
+ return []
+
+ lines = []
+ lines.append(f'uint8_t {config_type}_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) {{')
+
+ for matrix, indexes in led_map.items():
+ if len(indexes) > 1:
+ # Match last one wins behavior of _gen_led_config w.r.t. g_led_config matrix generation
+ last_index = indexes[-1]
+ other_indexes = indexes[:-1]
+
+ lines.append(f'#if LED_HITS_TO_REMEMBER < {len(indexes)}')
+ lines.append(f'# pragma message("LED_HITS_TO_REMEMBER is not large enough to handle matrix{list(matrix)} indexes{indexes}")')
+ lines.append('#else')
+ lines.append(f' if (row == {matrix[0]} && column == {matrix[1]}) {{')
+ lines.append(f' // {last_index} will be added by the default lookup code that runs after this')
+
+ for index, led_index in enumerate(other_indexes):
+ lines.append(f' led_i[{index}] = {led_index};')
+
+ lines.append(f' return {len(other_indexes)};')
+ lines.append(' }')
+ lines.append('#endif')
+
+ lines.append(' return 0;')
+ lines.append('}')
lines.append('')
return lines
@@ -207,10 +256,13 @@ class Layout:
def _gen_chordal_hold_layout(info_data):
"""Convert info.json content to chordal_hold_layout
"""
+ layouts = info_data.get('layouts', {})
+ if not layouts:
+ return []
+
# NOTE: If there are multiple layouts, only the first is read.
- for layout_name, layout_json in info_data['layouts'].items():
- layout = Layout(layout_json)
- break
+ layout_name, layout_json = next(iter(layouts.items()))
+ layout = Layout(layout_json)
if layout.is_symmetric():
# If the layout is symmetric (e.g. most split keyboards), guess the
diff --git a/lib/python/qmk/cli/generate/keycodes.py b/lib/python/qmk/cli/generate/keycodes.py
index d694202aecd..f5aec1f180c 100644
--- a/lib/python/qmk/cli/generate/keycodes.py
+++ b/lib/python/qmk/cli/generate/keycodes.py
@@ -58,7 +58,7 @@ def _generate_defines(lines, keycodes):
lines.append('')
lines.append('// Alias')
- for key, value in keycodes["keycodes"].items():
+ for value in keycodes["keycodes"].values():
temp = value.get("key")
for alias in value.get("aliases", []):
lines.append(f' {alias.ljust(10)} = {temp},')
@@ -120,7 +120,7 @@ def _generate_aliases(lines, keycodes):
lines.append(f'#define {define} {val}')
lines.append('')
- for key, value in keycodes["aliases"].items():
+ for value in keycodes["aliases"].values():
for alias in value.get("aliases", []):
lines.append(f'#define {alias} {value.get("key")}')
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py
index f9f40e74a80..2f95ade26f6 100644
--- a/lib/python/qmk/cli/lint.py
+++ b/lib/python/qmk/cli/lint.py
@@ -271,7 +271,7 @@ def keymap_check(kb, km):
return ok
-def keyboard_check(kb): # noqa C901
+def keyboard_check(kb): # noqa: C901
"""Perform the keyboard level checks.
"""
ok = True
diff --git a/lib/python/qmk/cli/mass_compile.py b/lib/python/qmk/cli/mass_compile.py
index 732d778e7af..a9fbcf82cff 100755
--- a/lib/python/qmk/cli/mass_compile.py
+++ b/lib/python/qmk/cli/mass_compile.py
@@ -2,6 +2,7 @@
This will compile everything in parallel, for testing purposes.
"""
+
import os
from typing import List
from pathlib import Path
@@ -37,19 +38,16 @@ def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool,
builddir.mkdir(parents=True, exist_ok=True)
with open(makefile, "w") as f:
- # yapf: disable
- f.write(
- f"""\
+ # fmt: off
+ f.write("""\
# This file is auto-generated by qmk mass-compile
# Do not edit this file directly.
all: print_failures
.PHONY: all_targets print_failures
print_failures: all_targets
-"""# noqa
- )
+""")
if print_failures:
- f.write(
- f"""\
+ f.write(f"""\
@for f in $$(ls .build/failed.log.{os.getpid()}.* 2>/dev/null | sort); do \\
echo; \\
echo "======================================================================================"; \\
@@ -58,9 +56,8 @@ print_failures: all_targets
cat $$f; \\
echo "------------------------------------------------------"; \\
done
-"""# noqa
- )
- # yapf: enable
+""") # noqa: W191, E101
+ # fmt: on
for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)):
keyboard_name = target.keyboard
keymap_name = target.keymap
@@ -78,9 +75,8 @@ print_failures: all_targets
build_log += f".{extra_args}"
failed_log += f".{extra_args}"
target_suffix = f"_{extra_args}"
- # yapf: disable
- f.write(
- f"""\
+ # fmt: off
+ f.write(f"""\
.PHONY: {target_filename}{target_suffix}_binary
all_targets: {target_filename}{target_suffix}_binary
{target_filename}{target_suffix}_binary:
@@ -93,20 +89,17 @@ all_targets: {target_filename}{target_suffix}_binary
|| {{ grep '\\[WARNINGS\\]' "{build_log}" >/dev/null 2>&1 && printf "Build %-64s \\e[1;33m[WARNINGS]\\e[0m\\n" "{keyboard_name}:{keymap_name}" ; }} \\
|| printf "Build %-64s \\e[1;32m[OK]\\e[0m\\n" "{keyboard_name}:{keymap_name}"
@rm -f "{build_log}" || true
-"""# noqa
- )
- # yapf: enable
+""") # noqa: W191, E101
+ # fmt: on
if no_temp:
- # yapf: disable
- f.write(
- f"""\
+ # fmt: off
+ f.write(f"""\
@rm -rf "{builddir}/{target_filename}.elf" 2>/dev/null || true
@rm -rf "{builddir}/{target_filename}.map" 2>/dev/null || true
@rm -rf "{builddir}/obj_{target_filename}" || true
-"""# noqa
- )
- # yapf: enable
+""") # noqa: W191, E101
+ # fmt: on
f.write('\n')
cli.run([find_make(), *get_make_parallel_args(parallel), '-f', makefile.as_posix(), 'all'], capture_output=False, stdin=DEVNULL)
@@ -123,21 +116,12 @@ all_targets: {target_filename}{target_suffix}_binary
@cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the commands to be run.")
@cli.argument('-p', '--print-failures', arg_only=True, action='store_true', help="Print failed builds.")
-@cli.argument(
- '-f',
- '--filter',
- arg_only=True,
- action='append',
- default=[],
- help= # noqa: `format-python` and `pytest` don't agree here.
- "Filter the list of keyboards based on the supplied value in rules.mk. Matches info.json structure, and accepts the formats 'features.rgblight=true' or 'exists(matrix_pins.direct)'. May be passed multiple times, all filters need to match. Value may include wildcards such as '*' and '?'." # noqa: `format-python` and `pytest` don't agree here.
-)
+@cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help="Filter the list of keyboards based on the supplied value in rules.mk. Matches info.json structure, and accepts the formats 'features.rgblight==true' or 'exists(matrix_pins.direct)'. May be passed multiple times, all filters need to match. Value may include wildcards such as '*' and '?'.") # fmt: off
@cli.argument('-km', '--keymap', type=str, default='default', help="The keymap name to build. Default is 'default'.")
@cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.")
@cli.subcommand('Compile QMK Firmware for all keyboards.', hidden=False if cli.config.user.developer else True)
def mass_compile(cli):
- """Compile QMK Firmware against all keyboards.
- """
+ """Compile QMK Firmware against all keyboards."""
maybe_exit_config(should_exit=False, should_reraise=True)
if len(cli.args.builds) > 0:
diff --git a/lib/python/qmk/cli/new/keyboard.py b/lib/python/qmk/cli/new/keyboard.py
index dd1d06e1891..c4707247573 100644
--- a/lib/python/qmk/cli/new/keyboard.py
+++ b/lib/python/qmk/cli/new/keyboard.py
@@ -6,6 +6,7 @@ import shutil
from datetime import date
from pathlib import Path
from dotty_dict import dotty
+from functools import lru_cache
from milc import cli
from milc.questions import choice, question, yesno
@@ -20,17 +21,28 @@ from qmk.constants import MCU2BOOTLOADER, QMK_FIRMWARE
COMMUNITY = Path('layouts/default/')
TEMPLATE = Path('data/templates/keyboard/')
-# defaults
-schema = dotty(load_jsonschema('keyboard'))
-mcu_types = sorted(schema["properties.processor.enum"], key=str.casefold)
-dev_boards = sorted(schema["properties.development_board.enum"], key=str.casefold)
-available_layouts = sorted([x.name for x in COMMUNITY.iterdir() if x.is_dir()])
+
+@lru_cache(maxsize=1)
+def _keyboard_schema():
+ return dotty(load_jsonschema('keyboard'))
+
+
+def _processor_types():
+ return sorted(_keyboard_schema()["properties.processor.enum"], key=str.casefold)
+
+
+def _dev_boards():
+ return sorted(_keyboard_schema()["properties.development_board.enum"], key=str.casefold)
+
+
+def _available_layouts():
+ return sorted([x.name for x in COMMUNITY.iterdir() if x.is_dir()])
def mcu_type(mcu):
"""Callable for argparse validation.
"""
- if mcu not in (dev_boards + mcu_types):
+ if mcu not in (_dev_boards() + _processor_types()):
raise ValueError
return mcu
@@ -38,7 +50,7 @@ def mcu_type(mcu):
def layout_type(layout):
"""Callable for argparse validation.
"""
- if layout not in available_layouts:
+ if layout not in _available_layouts():
raise ValueError
return layout
@@ -162,7 +174,7 @@ def prompt_layout():
bootstrap the process""")
# avoid overwhelming user - remove some?
- filtered_layouts = [x for x in available_layouts if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])]
+ filtered_layouts = [x for x in _available_layouts() if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])]
filtered_layouts.append("none of the above")
return choice("Default Layout?", filtered_layouts, default=len(filtered_layouts) - 1)
@@ -184,7 +196,7 @@ def prompt_dev_board():
prompt_heading_subheading("Select Development Board", """For more information, see:
https://docs.qmk.fm/compatible_microcontrollers""")
- filtered_dev_boards = dev_boards.copy()
+ filtered_dev_boards = _dev_boards()
filtered_dev_boards.append("none of the above")
return choice("Development Board?", filtered_dev_boards, default=len(filtered_dev_boards) - 1)
@@ -195,7 +207,7 @@ def prompt_mcu():
https://docs.qmk.fm/compatible_microcontrollers""")
# remove any options strictly used for compatibility
- filtered_mcu = [x for x in mcu_types if not any(xs in x for xs in ['cortex', 'unknown'])]
+ filtered_mcu = [x for x in _processor_types() if not any(xs in x for xs in ['cortex', 'unknown'])]
return choice("Microcontroller?", filtered_mcu, default=filtered_mcu.index("atmega32u4"))
@@ -235,7 +247,7 @@ def new_keyboard(cli):
mcu = prompt_mcu()
config = {}
- if mcu in dev_boards:
+ if mcu in _dev_boards():
config['development_board'] = mcu
else:
config['processor'] = mcu
diff --git a/lib/python/qmk/flashers.py b/lib/python/qmk/flashers.py
index 2705bb7d5b9..41b9b35af8c 100644
--- a/lib/python/qmk/flashers.py
+++ b/lib/python/qmk/flashers.py
@@ -9,7 +9,6 @@ import usb.core
from qmk.constants import BOOTLOADER_VIDS_PIDS
from milc import cli
-# yapf: disable
_PID_TO_MCU = {
'2fef': 'atmega16u2',
'2ff0': 'atmega32u2',
@@ -17,7 +16,7 @@ _PID_TO_MCU = {
'2ff4': 'atmega32u4',
'2ff9': 'at90usb64',
'2ffa': 'at90usb162',
- '2ffb': 'at90usb128'
+ '2ffb': 'at90usb128',
}
AVRDUDE_MCU = {
@@ -25,7 +24,6 @@ AVRDUDE_MCU = {
'atmega328p': 'm328p',
'atmega328': 'm328',
}
-# yapf: enable
class DelayedKeyboardInterrupt:
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 44fed0843ce..8c5cdfb09d1 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -121,7 +121,7 @@ def _validate_build_target(keyboard, info_data):
_log_warning(info_data, 'Build marker "keyboard.json" not found.')
-def _validate_layouts(keyboard, info_data): # noqa C901
+def _validate_layouts(keyboard, info_data): # noqa: C901
"""Non schema checks
"""
col_num = info_data.get('matrix_size', {}).get('cols', 0)
diff --git a/lib/python/qmk/json_encoders.py b/lib/python/qmk/json_encoders.py
index 6bad820a764..dd130424057 100755
--- a/lib/python/qmk/json_encoders.py
+++ b/lib/python/qmk/json_encoders.py
@@ -3,6 +3,7 @@
import json
from decimal import Decimal
+_sentinel = object()
newline = '\n'
@@ -66,9 +67,12 @@ class QMKJSONEncoder(json.JSONEncoder):
return "[\n" + ",\n".join(output) + "\n" + self.indent_str + "]"
- def encode(self, obj, path=[]):
+ def encode(self, obj, path=_sentinel):
"""Encode JSON objects for QMK.
"""
+ if path is _sentinel:
+ path = []
+
if isinstance(obj, Decimal):
return self.encode_decimal(obj)
diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py
index e8534492c99..151f1df6785 100644
--- a/lib/python/qmk/keyboard.py
+++ b/lib/python/qmk/keyboard.py
@@ -140,15 +140,21 @@ def keyboard_aliases(keyboard):
Includes the keyboard itself.
"""
- aliases = json_load(Path('data/mappings/keyboard_aliases.hjson'))
+ aliases = keyboard_alias_definitions()
- if keyboard in aliases:
- keyboard = aliases[keyboard].get('target', keyboard)
+ def _resolve_recursive_aliases(kb):
+ ret = set()
+ for found in filter(lambda k: aliases[k].get('target', '') == kb, aliases.keys()):
+ ret.update(_resolve_recursive_aliases(found))
+ ret.add(found)
+ return ret
- keyboards = set(filter(lambda k: aliases[k].get('target', '') == keyboard, aliases.keys()))
+ keyboard = keyboard_folder(keyboard)
+
+ keyboards = _resolve_recursive_aliases(keyboard)
keyboards.add(keyboard)
- keyboards = list(sorted(keyboards))
- return keyboards
+
+ return list(sorted(keyboards))
def keyboard_folder_or_all(keyboard):
@@ -224,8 +230,8 @@ def rules_mk(keyboard):
keyboard = Path(keyboard)
rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk')
- for i, dir in enumerate(keyboard.parts):
- cur_dir = cur_dir / dir
+ for folder in keyboard.parts:
+ cur_dir = cur_dir / folder
rules = parse_rules_mk_file(cur_dir / 'rules.mk', rules)
return rules
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py
index fa8f5df5f91..fe1abfd0dc3 100644
--- a/lib/python/qmk/keymap.py
+++ b/lib/python/qmk/keymap.py
@@ -476,7 +476,7 @@ def _c_preprocess(path, stdin=DEVNULL):
return pre_processed_keymap.stdout
-def _get_layers(keymap): # noqa C901 : until someone has a good idea how to simplify/split up this code
+def _get_layers(keymap): # noqa: C901 until someone has a good idea how to simplify/split up this code
""" Find the layers in a keymap.c file.
Args:
diff --git a/lib/python/qmk/painter.py b/lib/python/qmk/painter.py
index 1a07f7442cd..9635512c494 100644
--- a/lib/python/qmk/painter.py
+++ b/lib/python/qmk/painter.py
@@ -123,7 +123,7 @@ def _render_image_metadata(metadata):
continue
# Unpack rect's coords
- l, t, r, b = v["delta_rect"]
+ l, t, r, b = v["delta_rect"] # noqa: E741
delta_px = (r - l) * (b - t)
px = size["width"] * size["height"]
@@ -143,7 +143,7 @@ def command_args_str(cli, command_name):
args = {}
max_length = 0
- for arg_name, was_passed in cli.args_passed[command_name].items():
+ for arg_name in cli.args_passed[command_name].keys():
max_length = max(max_length, len(arg_name))
val = getattr(cli.args, arg_name.replace("-", "_"))
diff --git a/lib/python/qmk/search.py b/lib/python/qmk/search.py
index c7bce344ad1..a34b8cfaeac 100644
--- a/lib/python/qmk/search.py
+++ b/lib/python/qmk/search.py
@@ -7,7 +7,7 @@ import fnmatch
import json
import logging
import re
-from typing import Callable, Dict, List, Optional, Tuple, Union
+from typing import Callable, Dict, List, Optional, Tuple, Union, Sequence
from dotty_dict import dotty, Dotty
from milc import cli
@@ -226,7 +226,7 @@ def _construct_build_target(e: KeyboardKeymapDesc):
return e.to_build_target()
-def _filter_keymap_targets(target_list: List[KeyboardKeymapDesc], filters: List[str] = []) -> List[KeyboardKeymapDesc]:
+def _filter_keymap_targets(target_list: List[KeyboardKeymapDesc], filters: Sequence[str] = []) -> List[KeyboardKeymapDesc]:
"""Filter a list of KeyboardKeymapDesc based on the supplied filters.
Optionally includes the values of the queried info.json keys.
@@ -306,7 +306,7 @@ def _filter_keymap_targets(target_list: List[KeyboardKeymapDesc], filters: List[
return targets
-def search_keymap_targets(targets: List[Union[Tuple[str, str], Tuple[str, str, Dict[str, str]]]] = [('all', 'default')], filters: List[str] = []) -> List[BuildTarget]:
+def search_keymap_targets(targets: List[Union[Tuple[str, str], Tuple[str, str, Dict[str, str]]]], filters: Sequence[str] = []) -> List[BuildTarget]:
"""Search for build targets matching the supplied criteria.
"""
def _make_desc(e):
@@ -321,7 +321,7 @@ def search_keymap_targets(targets: List[Union[Tuple[str, str], Tuple[str, str, D
return sorted(targets)
-def search_make_targets(targets: List[Union[str, Tuple[str, Dict[str, str]]]], filters: List[str] = []) -> List[BuildTarget]:
+def search_make_targets(targets: List[Union[str, Tuple[str, Dict[str, str]]]], filters: Sequence[str] = []) -> List[BuildTarget]:
"""Search for build targets matching the supplied criteria.
"""
targets = _filter_keymap_targets(expand_make_targets(targets), filters)
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
index 2716459989f..58d7636e639 100644
--- a/lib/python/qmk/tests/test_cli_commands.py
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -1,3 +1,5 @@
+from typing import Sequence
+
import platform
from subprocess import DEVNULL
@@ -21,7 +23,7 @@ def check_subcommand_stdin(file_to_read, command, *args):
return result
-def check_returncode(result, expected=[0]):
+def check_returncode(result, expected: Sequence[int] = [0]):
"""Print stdout if `result.returncode` does not match `expected`.
"""
if result.returncode not in expected:
diff --git a/lib/python/qmk/userspace.py b/lib/python/qmk/userspace.py
index 881490f7964..65ac6ac19d7 100644
--- a/lib/python/qmk/userspace.py
+++ b/lib/python/qmk/userspace.py
@@ -75,7 +75,7 @@ class UserspaceDefs:
validate(json, 'qmk.user_repo.v0') # `qmk.json` must have a userspace_version at minimum
except jsonschema.ValidationError as err:
exception.add('qmk.user_repo.v0', err)
- raise exception
+ raise exception from None
# Iterate through each version of the schema, starting with the latest and decreasing to v1
schema_versions = [
diff --git a/modules/qmk/nvm_test/config.h b/modules/qmk/nvm_test/config.h
new file mode 100644
index 00000000000..1d98b69e7be
--- /dev/null
+++ b/modules/qmk/nvm_test/config.h
@@ -0,0 +1,5 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#define EECONFIG_MODULE_NVM_TEST_DATA_SIZE 4
diff --git a/modules/qmk/nvm_test/nvm_test.c b/modules/qmk/nvm_test/nvm_test.c
new file mode 100644
index 00000000000..46efa0c3dfd
--- /dev/null
+++ b/modules/qmk/nvm_test/nvm_test.c
@@ -0,0 +1,56 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include
+#include "community_modules.h"
+#include "debug.h"
+#include "timer.h"
+#include "eeconfig.h"
+
+ASSERT_COMMUNITY_MODULES_MIN_API_VERSION(1, 1, 3);
+
+typedef struct my_config_t {
+ uint32_t data;
+} my_config_t;
+
+static my_config_t config;
+
+// Helpers required to bind to debounce helper
+void eeconfig_read_my_config(my_config_t *value) {
+ eeconfig_read_nvm_test_datablock(value, 0, sizeof(my_config_t));
+}
+void eeconfig_update_my_config(my_config_t *value) {
+ eeconfig_update_nvm_test_datablock(value, 0, sizeof(my_config_t));
+}
+
+EECONFIG_DEBOUNCE_HELPER(my_config, config);
+
+void eeconfig_init_nvm_test_datablock(void) {
+ my_config_t default_config = {
+ .data = 42,
+ };
+ eeconfig_update_nvm_test_datablock(&default_config, 0, sizeof(my_config_t));
+}
+
+void keyboard_post_init_nvm_test(void) {
+ eeconfig_init_my_config();
+}
+
+bool process_record_nvm_test(uint16_t keycode, keyrecord_t *record) {
+ if (!record->event.pressed) {
+ config.data += 1;
+ eeconfig_flag_my_config(true);
+ }
+
+ return true;
+}
+
+void housekeeping_task_nvm_test(void) {
+ eeconfig_flush_my_config(false);
+
+ static uint32_t last_sync = 0;
+ if (timer_elapsed32(last_sync) > 1000) {
+ last_sync = timer_read32();
+
+ dprintf("Config: %ld\n", config.data);
+ }
+}
diff --git a/modules/qmk/nvm_test/qmk_module.json b/modules/qmk/nvm_test/qmk_module.json
new file mode 100644
index 00000000000..26146f6d075
--- /dev/null
+++ b/modules/qmk/nvm_test/qmk_module.json
@@ -0,0 +1,5 @@
+{
+ "module_name": "Example nvm persistence",
+ "maintainer": "QMK Maintainers",
+ "license": "GPL-2.0-or-later"
+}
diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c
index 1c61f196bde..3b18f4f4b8b 100644
--- a/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c
+++ b/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c
@@ -21,8 +21,16 @@
# endif
#endif
-#if PS2_DATA_PIN + 1 != PS2_CLOCK_PIN
-# error PS/2 clock pin must be data pin + 1!
+#if PS2_DATA_PIN + 1 == PS2_CLOCK_PIN
+# define PS2_FIRST_PIN PS2_DATA_PIN
+# define PS2_DATA_PINDIR_BIT 1
+# define PS2_CLOCK_PINDIR_BIT 2
+#elif PS2_DATA_PIN - 1 == PS2_CLOCK_PIN
+# define PS2_FIRST_PIN PS2_CLOCK_PIN
+# define PS2_DATA_PINDIR_BIT 2
+# define PS2_CLOCK_PINDIR_BIT 1
+#else
+# error PS/2 clock and data pin must be consecutive!
#endif
static inline void pio_serve_interrupt(void);
@@ -50,29 +58,29 @@ OSAL_IRQ_HANDLER(RP_PIO0_IRQ_0_HANDLER) {
// clang-format off
static const uint16_t ps2_program_instructions[] = {
- // .wrap_target
- 0x00c7, // 0: jmp pin, 7
- 0xe02a, // 1: set x, 10
- 0x2021, // 2: wait 0 pin, 1
- 0x4001, // 3: in pins, 1
- 0x20a1, // 4: wait 1 pin, 1
- 0x0042, // 5: jmp x--, 2
- 0x0000, // 6: jmp 0
- 0x00e9, // 7: jmp !osre, 9
- 0x0000, // 8: jmp 0
- 0xff81, // 9: set pindirs, 1 [31]
- 0xe280, // 10: set pindirs, 0 [2]
- 0xe082, // 11: set pindirs, 2
- 0x2021, // 12: wait 0 pin, 1
- 0xe029, // 13: set x, 9
- 0x6081, // 14: out pindirs, 1
- 0x20a1, // 15: wait 1 pin, 1
- 0x2021, // 16: wait 0 pin, 1
- 0x004e, // 17: jmp x--, 14
- 0xe083, // 18: set pindirs, 3
- 0x2021, // 19: wait 0 pin, 1
- 0x20a1, // 20: wait 1 pin, 1
- // .wrap
+ // .wrap_target
+ 0x00c7, // 0: jmp pin, 7
+ 0xe02a, // 1: set x, 10
+ 0x2000 | PS2_CLOCK_PIN, // 2: wait 0 gpio, CLK
+ 0x4001, // 3: in pins, 1
+ 0x2080 | PS2_CLOCK_PIN, // 4: wait 1 gpio, CLK
+ 0x0042, // 5: jmp x--, 2
+ 0x0000, // 6: jmp 0
+ 0x00e9, // 7: jmp !osre, 9
+ 0x0000, // 8: jmp 0
+ 0xff80 | PS2_DATA_PINDIR_BIT, // 9: set pindirs, DATA [31]
+ 0xe280, // 10: set pindirs, 0 [2]
+ 0xe080 | PS2_CLOCK_PINDIR_BIT, // 11: set pindirs, CLK
+ 0x2000 | PS2_CLOCK_PIN, // 12: wait 0 gpio, CLK
+ 0xe029, // 13: set x, 9
+ 0x6081, // 14: out pindirs, 1
+ 0x2080 | PS2_CLOCK_PIN, // 15: wait 1 gpio, CLK
+ 0x2000 | PS2_CLOCK_PIN, // 16: wait 0 gpio, CLK
+ 0x004e, // 17: jmp x--, 14
+ 0xe083, // 18: set pindirs, 3
+ 0x2000 | PS2_CLOCK_PIN, // 19: wait 0 gpio, CLK
+ 0x2080 | PS2_CLOCK_PIN, // 20: wait 1 gpio, CLK
+ // .wrap
};
// clang-format on
@@ -133,9 +141,9 @@ void ps2_host_init(void) {
sm_config_set_wrap(&c, offset + PS2_WRAP_TARGET, offset + PS2_WRAP);
// Set pindirs to input (output enable is inverted below)
- pio_sm_set_consecutive_pindirs(pio, state_machine, PS2_DATA_PIN, 2, true);
+ pio_sm_set_consecutive_pindirs(pio, state_machine, PS2_FIRST_PIN, 2, true);
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (200.0f * KHZ));
- sm_config_set_set_pins(&c, PS2_DATA_PIN, 2);
+ sm_config_set_set_pins(&c, PS2_FIRST_PIN, 2);
sm_config_set_out_pins(&c, PS2_DATA_PIN, 1);
sm_config_set_out_shift(&c, true, true, 10);
sm_config_set_in_shift(&c, true, true, 11);
diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c
index a7d2a45a515..86d1dc84704 100644
--- a/quantum/backlight/backlight.c
+++ b/quantum/backlight/backlight.c
@@ -107,32 +107,44 @@ void backlight_toggle(void) {
/** \brief Enable backlight
*
- * FIXME: needs doc
+ * FIXME: needs doc
*/
-void backlight_enable(void) {
+void backlight_enable_noeeprom(void) {
if (backlight_config.enable) return; // do nothing if backlight is already on
backlight_config.enable = true;
if (backlight_config.raw == 1) // enabled but level == 0
backlight_config.level = 1;
- eeconfig_update_backlight(&backlight_config);
dprintf("backlight enable\n");
backlight_set(backlight_config.level);
}
+void backlight_enable(void) {
+ if (backlight_config.enable) return; // do nothing if backlight is already on
+
+ backlight_enable_noeeprom();
+ eeconfig_update_backlight(&backlight_config);
+}
+
/** \brief Disable backlight
*
- * FIXME: needs doc
+ * FIXME: needs doc
*/
-void backlight_disable(void) {
+void backlight_disable_noeeprom(void) {
if (!backlight_config.enable) return; // do nothing if backlight is already off
backlight_config.enable = false;
- eeconfig_update_backlight(&backlight_config);
dprintf("backlight disable\n");
backlight_set(0);
}
+void backlight_disable(void) {
+ if (!backlight_config.enable) return; // do nothing if backlight is already off
+
+ backlight_disable_noeeprom();
+ eeconfig_update_backlight(&backlight_config);
+}
+
/** /brief Get the backlight status
*
* FIXME: needs doc
diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h
index 2faa8fc4f2e..2c4b71eccb7 100644
--- a/quantum/backlight/backlight.h
+++ b/quantum/backlight/backlight.h
@@ -51,7 +51,9 @@ STATIC_ASSERT(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG
void backlight_init(void);
void backlight_toggle(void);
void backlight_enable(void);
+void backlight_enable_noeeprom(void);
void backlight_disable(void);
+void backlight_disable_noeeprom(void);
bool is_backlight_enabled(void);
void backlight_step(void);
void backlight_increase(void);
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index f14e6ddf97c..269c398cbc7 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -39,6 +39,10 @@
# include "connection.h"
#endif // CONNECTION_ENABLE
+#ifdef COMMUNITY_MODULES_ENABLE
+# include "community_modules.h"
+#endif
+
#ifdef VIA_ENABLE
bool via_eeprom_is_valid(void);
void via_eeprom_set_valid(bool valid);
@@ -116,7 +120,8 @@ void eeconfig_init_quantum(void) {
#endif // UNICODE_COMMON_ENABLE
#ifdef STENO_ENABLE
- eeconfig_update_steno_mode(0);
+ extern void eeconfig_update_steno_default(void);
+ eeconfig_update_steno_default();
#endif // STENO_ENABLE
#ifdef RGB_MATRIX_ENABLE
@@ -148,6 +153,10 @@ void eeconfig_init_quantum(void) {
eeconfig_init_user_datablock();
#endif // (EECONFIG_USER_DATA_SIZE) > 0
+#ifdef COMMUNITY_MODULES_ENABLE
+ eeconfig_init_modules_datablock();
+#endif // COMMUNITY_MODULES_ENABLE
+
#if defined(VIA_ENABLE)
// Invalidate VIA eeprom config, and then reset.
// Just in case if power is lost mid init, this makes sure that it gets
@@ -357,3 +366,21 @@ __attribute__((weak)) void eeconfig_init_user_datablock(void) {
nvm_eeconfig_init_user_datablock();
}
#endif // (EECONFIG_USER_DATA_SIZE) > 0
+
+void eeconfig_prepare_datablocks(void) {
+#if (EECONFIG_KB_DATA_SIZE) > 0
+ if (!eeconfig_is_kb_datablock_valid()) {
+ eeconfig_init_kb_datablock();
+ }
+#endif // (EECONFIG_KB_DATA_SIZE) > 0
+
+#if (EECONFIG_USER_DATA_SIZE) > 0
+ if (!eeconfig_is_user_datablock_valid()) {
+ eeconfig_init_user_datablock();
+ }
+#endif // (EECONFIG_USER_DATA_SIZE) > 0
+
+#ifdef COMMUNITY_MODULES_ENABLE
+ eeconfig_prepare_modules_datablocks();
+#endif // COMMUNITY_MODULES_ENABLE
+}
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index 66f8934a99e..f23de1d6570 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -63,6 +63,8 @@ void eeconfig_init_user(void);
void eeconfig_enable(void);
void eeconfig_disable(void);
+void eeconfig_prepare_datablocks(void);
+
typedef union debug_config_t debug_config_t;
void eeconfig_read_debug(debug_config_t *debug_config) __attribute__((nonnull));
void eeconfig_update_debug(const debug_config_t *debug_config) __attribute__((nonnull));
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index 5a80facf57f..9cb555fc8d5 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -76,7 +76,7 @@ along with this program. If not, see .
# include "process_tap_dance.h"
#endif
#ifdef STENO_ENABLE
-# include "process_steno.h"
+# include "steno.h"
#endif
#ifdef KEY_OVERRIDE_ENABLE
# include "process_key_override.h"
@@ -150,6 +150,9 @@ along with this program. If not, see .
#ifdef CONNECTION_ENABLE
# include "connection.h"
#endif
+#ifdef SEQUENCER_ENABLE
+# include "sequencer.h"
+#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) {
@@ -449,6 +452,8 @@ void quantum_init(void) {
/* Also initialize layer state to trigger callback functions for layer_state */
layer_state_set_kb((layer_state_t)layer_state);
+
+ eeconfig_prepare_datablocks();
}
/** \brief keyboard_init
@@ -507,7 +512,7 @@ void keyboard_init(void) {
#ifdef RGBLIGHT_ENABLE
rgblight_init();
#endif
-#ifdef STENO_ENABLE_ALL
+#ifdef STENO_ENABLE
steno_init();
#endif
#ifdef DIP_SWITCH_ENABLE
diff --git a/quantum/keycodes.h b/quantum/keycodes.h
index 132eb79c6e1..931e195ca18 100644
--- a/quantum/keycodes.h
+++ b/quantum/keycodes.h
@@ -26,11 +26,11 @@
#pragma once
// clang-format off
-#define QMK_KEYCODES_VERSION "0.0.8"
-#define QMK_KEYCODES_VERSION_BCD 0x00000008
+#define QMK_KEYCODES_VERSION "0.0.9"
+#define QMK_KEYCODES_VERSION_BCD 0x00000009
#define QMK_KEYCODES_VERSION_MAJOR 0
#define QMK_KEYCODES_VERSION_MINOR 0
-#define QMK_KEYCODES_VERSION_PATCH 8
+#define QMK_KEYCODES_VERSION_PATCH 9
enum qk_keycode_ranges {
// Ranges
@@ -77,7 +77,7 @@ enum qk_keycode_ranges {
QK_AUDIO = 0x7480,
QK_AUDIO_MAX = 0x74BF,
QK_STENO = 0x74C0,
- QK_STENO_MAX = 0x74FF,
+ QK_STENO_MAX = 0x751F,
QK_MACRO = 0x7700,
QK_MACRO_MAX = 0x777F,
QK_CONNECTION = 0x7780,
@@ -596,10 +596,89 @@ enum qk_keycode_defines {
QK_MUSIC_MODE_NEXT = 0x7493,
QK_AUDIO_VOICE_NEXT = 0x7494,
QK_AUDIO_VOICE_PREVIOUS = 0x7495,
- QK_STENO_BOLT = 0x74F0,
- QK_STENO_GEMINI = 0x74F1,
- QK_STENO_COMB = 0x74F2,
- QK_STENO_COMB_MAX = 0x74FC,
+ QK_STENO_FUNCTION = 0x74C0,
+ QK_STENO_N1 = 0x74C1,
+ QK_STENO_N2 = 0x74C2,
+ QK_STENO_N3 = 0x74C3,
+ QK_STENO_N4 = 0x74C4,
+ QK_STENO_N5 = 0x74C5,
+ QK_STENO_N6 = 0x74C6,
+ QK_STENO_S1 = 0x74C7,
+ QK_STENO_S2 = 0x74C8,
+ QK_STENO_TL = 0x74C9,
+ QK_STENO_KL = 0x74CA,
+ QK_STENO_PL = 0x74CB,
+ QK_STENO_WL = 0x74CC,
+ QK_STENO_HL = 0x74CD,
+ QK_STENO_RL = 0x74CE,
+ QK_STENO_A = 0x74CF,
+ QK_STENO_O = 0x74D0,
+ QK_STENO_ST1 = 0x74D1,
+ QK_STENO_ST2 = 0x74D2,
+ QK_STENO_RESET1 = 0x74D3,
+ QK_STENO_RESET2 = 0x74D4,
+ QK_STENO_POWER = 0x74D5,
+ QK_STENO_ST3 = 0x74D6,
+ QK_STENO_ST4 = 0x74D7,
+ QK_STENO_E = 0x74D8,
+ QK_STENO_U = 0x74D9,
+ QK_STENO_FR = 0x74DA,
+ QK_STENO_RR = 0x74DB,
+ QK_STENO_PR = 0x74DC,
+ QK_STENO_BR = 0x74DD,
+ QK_STENO_LR = 0x74DE,
+ QK_STENO_GR = 0x74DF,
+ QK_STENO_TR = 0x74E0,
+ QK_STENO_SR = 0x74E1,
+ QK_STENO_DR = 0x74E2,
+ QK_STENO_N7 = 0x74E3,
+ QK_STENO_N8 = 0x74E4,
+ QK_STENO_N9 = 0x74E5,
+ QK_STENO_NA = 0x74E6,
+ QK_STENO_NB = 0x74E7,
+ QK_STENO_NC = 0x74E8,
+ QK_STENO_ZR = 0x74E9,
+ QK_STENO_X1 = 0x74EA,
+ QK_STENO_X2 = 0x74EB,
+ QK_STENO_X3 = 0x74EC,
+ QK_STENO_X4 = 0x74ED,
+ QK_STENO_X5 = 0x74EE,
+ QK_STENO_X6 = 0x74EF,
+ QK_STENO_X7 = 0x74F0,
+ QK_STENO_X8 = 0x74F1,
+ QK_STENO_X9 = 0x74F2,
+ QK_STENO_X10 = 0x74F3,
+ QK_STENO_X11 = 0x74F4,
+ QK_STENO_X12 = 0x74F5,
+ QK_STENO_X13 = 0x74F6,
+ QK_STENO_X14 = 0x74F7,
+ QK_STENO_X15 = 0x74F8,
+ QK_STENO_X16 = 0x74F9,
+ QK_STENO_X17 = 0x74FA,
+ QK_STENO_X18 = 0x74FB,
+ QK_STENO_X19 = 0x74FC,
+ QK_STENO_X20 = 0x74FD,
+ QK_STENO_X21 = 0x74FE,
+ QK_STENO_X22 = 0x74FF,
+ QK_STENO_X23 = 0x7500,
+ QK_STENO_X24 = 0x7501,
+ QK_STENO_X25 = 0x7502,
+ QK_STENO_X26 = 0x7503,
+ QK_STENO_S3 = 0x750B,
+ QK_STENO_TKL = 0x750C,
+ QK_STENO_PWL = 0x750D,
+ QK_STENO_HRL = 0x750E,
+ QK_STENO_FRR = 0x750F,
+ QK_STENO_PBR = 0x7510,
+ QK_STENO_LGR = 0x7511,
+ QK_STENO_TSR = 0x7512,
+ QK_STENO_DZR = 0x7513,
+ QK_STENO_AO = 0x7514,
+ QK_STENO_EU = 0x7515,
+ QK_STENO_MODE_BOLT = 0x751C,
+ QK_STENO_MODE_GEMINI = 0x751D,
+ QK_STENO_MODE_NEXT = 0x751E,
+ QK_STENO_MODE_PREVIOUS = 0x751F,
QK_MACRO_0 = 0x7700,
QK_MACRO_1 = 0x7701,
QK_MACRO_2 = 0x7702,
@@ -1293,6 +1372,94 @@ enum qk_keycode_defines {
MU_NEXT = QK_MUSIC_MODE_NEXT,
AU_NEXT = QK_AUDIO_VOICE_NEXT,
AU_PREV = QK_AUDIO_VOICE_PREVIOUS,
+ ST_FN = QK_STENO_FUNCTION,
+ ST_N1 = QK_STENO_N1,
+ ST_NUM = QK_STENO_N1,
+ ST_N2 = QK_STENO_N2,
+ ST_N3 = QK_STENO_N3,
+ ST_N4 = QK_STENO_N4,
+ ST_N5 = QK_STENO_N5,
+ ST_N6 = QK_STENO_N6,
+ ST_S1 = QK_STENO_S1,
+ ST_SL = QK_STENO_S1,
+ ST_S2 = QK_STENO_S2,
+ ST_TL = QK_STENO_TL,
+ ST_KL = QK_STENO_KL,
+ ST_PL = QK_STENO_PL,
+ ST_WL = QK_STENO_WL,
+ ST_HL = QK_STENO_HL,
+ ST_RL = QK_STENO_RL,
+ ST_A = QK_STENO_A,
+ ST_O = QK_STENO_O,
+ ST_ST1 = QK_STENO_ST1,
+ ST_STR = QK_STENO_ST1,
+ ST_ST2 = QK_STENO_ST2,
+ ST_RE1 = QK_STENO_RESET1,
+ ST_RES1 = QK_STENO_RESET1,
+ ST_RE2 = QK_STENO_RESET2,
+ ST_RES2 = QK_STENO_RESET2,
+ ST_PWR = QK_STENO_POWER,
+ ST_ST3 = QK_STENO_ST3,
+ ST_ST4 = QK_STENO_ST4,
+ ST_E = QK_STENO_E,
+ ST_U = QK_STENO_U,
+ ST_FR = QK_STENO_FR,
+ ST_RR = QK_STENO_RR,
+ ST_PR = QK_STENO_PR,
+ ST_BR = QK_STENO_BR,
+ ST_LR = QK_STENO_LR,
+ ST_GR = QK_STENO_GR,
+ ST_TR = QK_STENO_TR,
+ ST_SR = QK_STENO_SR,
+ ST_DR = QK_STENO_DR,
+ ST_N7 = QK_STENO_N7,
+ ST_N8 = QK_STENO_N8,
+ ST_N9 = QK_STENO_N9,
+ ST_NA = QK_STENO_NA,
+ ST_NB = QK_STENO_NB,
+ ST_NC = QK_STENO_NC,
+ ST_ZR = QK_STENO_ZR,
+ ST_X1 = QK_STENO_X1,
+ ST_X2 = QK_STENO_X2,
+ ST_X3 = QK_STENO_X3,
+ ST_X4 = QK_STENO_X4,
+ ST_X5 = QK_STENO_X5,
+ ST_X6 = QK_STENO_X6,
+ ST_X7 = QK_STENO_X7,
+ ST_X8 = QK_STENO_X8,
+ ST_X9 = QK_STENO_X9,
+ ST_X10 = QK_STENO_X10,
+ ST_X11 = QK_STENO_X11,
+ ST_X12 = QK_STENO_X12,
+ ST_X13 = QK_STENO_X13,
+ ST_X14 = QK_STENO_X14,
+ ST_X15 = QK_STENO_X15,
+ ST_X16 = QK_STENO_X16,
+ ST_X17 = QK_STENO_X17,
+ ST_X18 = QK_STENO_X18,
+ ST_X19 = QK_STENO_X19,
+ ST_X20 = QK_STENO_X20,
+ ST_X21 = QK_STENO_X21,
+ ST_X22 = QK_STENO_X22,
+ ST_X23 = QK_STENO_X23,
+ ST_X24 = QK_STENO_X24,
+ ST_X25 = QK_STENO_X25,
+ ST_X26 = QK_STENO_X26,
+ ST_S3 = QK_STENO_S3,
+ ST_TKL = QK_STENO_TKL,
+ ST_PWL = QK_STENO_PWL,
+ ST_HRL = QK_STENO_HRL,
+ ST_FRR = QK_STENO_FRR,
+ ST_PBR = QK_STENO_PBR,
+ ST_LGR = QK_STENO_LGR,
+ ST_TSR = QK_STENO_TSR,
+ ST_DZR = QK_STENO_DZR,
+ ST_AO = QK_STENO_AO,
+ ST_EU = QK_STENO_EU,
+ ST_BOLT = QK_STENO_MODE_BOLT,
+ ST_GEMI = QK_STENO_MODE_GEMINI,
+ ST_NEXT = QK_STENO_MODE_NEXT,
+ ST_PREV = QK_STENO_MODE_PREVIOUS,
MC_0 = QK_MACRO_0,
MC_1 = QK_MACRO_1,
MC_2 = QK_MACRO_2,
@@ -1515,7 +1682,7 @@ enum qk_keycode_defines {
#define IS_JOYSTICK_KEYCODE(code) ((code) >= QK_JOYSTICK_BUTTON_0 && (code) <= QK_JOYSTICK_BUTTON_31)
#define IS_PROGRAMMABLE_BUTTON_KEYCODE(code) ((code) >= QK_PROGRAMMABLE_BUTTON_1 && (code) <= QK_PROGRAMMABLE_BUTTON_32)
#define IS_AUDIO_KEYCODE(code) ((code) >= QK_AUDIO_ON && (code) <= QK_AUDIO_VOICE_PREVIOUS)
-#define IS_STENO_KEYCODE(code) ((code) >= QK_STENO_BOLT && (code) <= QK_STENO_COMB_MAX)
+#define IS_STENO_KEYCODE(code) ((code) >= QK_STENO_FUNCTION && (code) <= QK_STENO_MODE_PREVIOUS)
#define IS_MACRO_KEYCODE(code) ((code) >= QK_MACRO_0 && (code) <= QK_MACRO_31)
#define IS_CONNECTION_KEYCODE(code) ((code) >= QK_OUTPUT_AUTO && (code) <= QK_BLUETOOTH_PROFILE5)
#define IS_BACKLIGHT_KEYCODE(code) ((code) >= QK_BACKLIGHT_ON && (code) <= QK_BACKLIGHT_TOGGLE_BREATHING)
@@ -1541,7 +1708,7 @@ enum qk_keycode_defines {
#define JOYSTICK_KEYCODE_RANGE QK_JOYSTICK_BUTTON_0 ... QK_JOYSTICK_BUTTON_31
#define PROGRAMMABLE_BUTTON_KEYCODE_RANGE QK_PROGRAMMABLE_BUTTON_1 ... QK_PROGRAMMABLE_BUTTON_32
#define AUDIO_KEYCODE_RANGE QK_AUDIO_ON ... QK_AUDIO_VOICE_PREVIOUS
-#define STENO_KEYCODE_RANGE QK_STENO_BOLT ... QK_STENO_COMB_MAX
+#define STENO_KEYCODE_RANGE QK_STENO_FUNCTION ... QK_STENO_MODE_PREVIOUS
#define MACRO_KEYCODE_RANGE QK_MACRO_0 ... QK_MACRO_31
#define CONNECTION_KEYCODE_RANGE QK_OUTPUT_AUTO ... QK_BLUETOOTH_PROFILE5
#define BACKLIGHT_KEYCODE_RANGE QK_BACKLIGHT_ON ... QK_BACKLIGHT_TOGGLE_BREATHING
diff --git a/quantum/led_matrix/animations/led_matrix_effects.inc b/quantum/led_matrix/animations/led_matrix_effects.inc
index ad1f46b2422..238e25d24b3 100644
--- a/quantum/led_matrix/animations/led_matrix_effects.inc
+++ b/quantum/led_matrix/animations/led_matrix_effects.inc
@@ -16,3 +16,4 @@
#include "solid_splash_anim.h"
#include "wave_left_right_anim.h"
#include "wave_up_down_anim.h"
+#include "typing_heatmap_anim.h"
diff --git a/quantum/led_matrix/animations/typing_heatmap_anim.h b/quantum/led_matrix/animations/typing_heatmap_anim.h
new file mode 100644
index 00000000000..84dee22f5a9
--- /dev/null
+++ b/quantum/led_matrix/animations/typing_heatmap_anim.h
@@ -0,0 +1,112 @@
+#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
+LED_MATRIX_EFFECT(TYPING_HEATMAP)
+# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
+# ifndef LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP
+# define LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP 32
+# endif
+
+# ifndef LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS
+# define LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 25
+# endif
+
+# ifndef LED_MATRIX_TYPING_HEATMAP_SPREAD
+# define LED_MATRIX_TYPING_HEATMAP_SPREAD 40
+# endif
+
+# ifndef LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT
+# define LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
+# endif
+void process_led_matrix_typing_heatmap(uint8_t row, uint8_t col) {
+# ifdef LED_MATRIX_TYPING_HEATMAP_SLIM
+ // Limit effect to pressed keys
+ g_led_frame_buffer[row][col] = qadd8(g_led_frame_buffer[row][col], LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP);
+# else
+ if (g_led_config.matrix_co[row][col] == NO_LED) { // skip as pressed key doesn't have an led position
+ return;
+ }
+ for (uint8_t i_row = 0; i_row < MATRIX_ROWS; i_row++) {
+ for (uint8_t i_col = 0; i_col < MATRIX_COLS; i_col++) {
+ if (g_led_config.matrix_co[i_row][i_col] == NO_LED) { // skip as target key doesn't have an led position
+ continue;
+ }
+ if (i_row == row && i_col == col) {
+ g_led_frame_buffer[row][col] = qadd8(g_led_frame_buffer[row][col], LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP);
+ } else {
+# define LED_DISTANCE(led_a, led_b) sqrt16(((int32_t)(led_a.x - led_b.x) * (int32_t)(led_a.x - led_b.x)) + ((int32_t)(led_a.y - led_b.y) * (int32_t)(led_a.y - led_b.y)))
+ uint8_t distance = LED_DISTANCE(g_led_config.point[g_led_config.matrix_co[row][col]], g_led_config.point[g_led_config.matrix_co[i_row][i_col]]);
+# undef LED_DISTANCE
+ if (distance <= LED_MATRIX_TYPING_HEATMAP_SPREAD) {
+ uint8_t amount = qsub8(LED_MATRIX_TYPING_HEATMAP_SPREAD, distance);
+ if (amount > LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT) {
+ amount = LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT;
+ }
+ g_led_frame_buffer[i_row][i_col] = qadd8(g_led_frame_buffer[i_row][i_col], amount);
+ }
+ }
+ }
+ }
+# endif
+}
+
+// A timer to track the last time we decremented all heatmap values.
+static uint16_t heatmap_decrease_timer;
+// Whether we should decrement the heatmap values during the next update.
+static bool decrease_heatmap_values;
+
+bool TYPING_HEATMAP(effect_params_t* params) {
+ LED_MATRIX_USE_LIMITS(led_min, led_max);
+
+ if (params->init) {
+ led_matrix_set_value_all(0);
+ memset(g_led_frame_buffer, 0, sizeof g_led_frame_buffer);
+ }
+
+ // The heatmap animation might run in several iterations depending on
+ // `LED_MATRIX_LED_PROCESS_LIMIT`, therefore we only want to update the
+ // timer when the animation starts.
+ if (params->iter == 0) {
+ decrease_heatmap_values = timer_elapsed(heatmap_decrease_timer) >= LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS;
+
+ // Restart the timer if we are going to decrease the heatmap this frame.
+ if (decrease_heatmap_values) {
+ heatmap_decrease_timer = timer_read();
+ }
+ }
+
+ // Render heatmap & decrease
+ uint8_t count = 0;
+ for (uint8_t row = 0; row < MATRIX_ROWS && count < LED_MATRIX_LED_PROCESS_LIMIT; row++) {
+ for (uint8_t col = 0; col < MATRIX_COLS && LED_MATRIX_LED_PROCESS_LIMIT; col++) {
+ uint8_t val = g_led_frame_buffer[row][col];
+
+ bool processed = false;
+
+ uint8_t led[LED_HITS_TO_REMEMBER];
+ uint8_t led_count = led_matrix_map_row_column_to_led(row, col, led);
+ for (uint8_t index = 0; index < led_count; index++) {
+ uint8_t led_index = led[index];
+
+ if (led_index >= led_min && led_index < led_max) {
+ count++;
+
+ if (!HAS_ANY_FLAGS(g_led_config.flags[led_index], params->flags)) {
+ continue;
+ }
+
+ uint8_t value = scale8(led_matrix_eeconfig.val, val);
+ led_matrix_set_value(led_index, value);
+ processed = true;
+ }
+ }
+
+ if (processed && decrease_heatmap_values) {
+ g_led_frame_buffer[row][col] = qsub8(val, 1);
+ }
+ }
+ }
+
+ return led_matrix_check_finished_leds(led_max);
+}
+
+# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index a751f08c758..806df00c95b 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -200,10 +200,10 @@ void led_matrix_handle_key_event(uint8_t row, uint8_t col, bool pressed) {
}
if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) {
- memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
- memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
- memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
- memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
+ memmove(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
last_hit_buffer.count = LED_HITS_TO_REMEMBER - led_count;
}
diff --git a/quantum/led_matrix/post_config.h b/quantum/led_matrix/post_config.h
index b6770b9ee1c..070976fdaac 100644
--- a/quantum/led_matrix/post_config.h
+++ b/quantum/led_matrix/post_config.h
@@ -5,6 +5,11 @@
// clang-format off
+// framebuffer
+#if defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
+# define LED_MATRIX_FRAMEBUFFER_EFFECTS
+#endif
+
// reactive
#if defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE) || \
defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || \
diff --git a/quantum/main.c b/quantum/main.c
index 3159c558507..6889ad3b346 100644
--- a/quantum/main.c
+++ b/quantum/main.c
@@ -55,6 +55,11 @@ int main(void) {
raw_hid_task();
#endif
+#ifdef PLOVER_HID_ENABLE
+ void plover_hid_task(void);
+ plover_hid_task();
+#endif
+
#ifdef CONSOLE_ENABLE
void console_task(void);
console_task();
diff --git a/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
index 78b8190eaf9..1bac5f6366b 100644
--- a/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
+++ b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h
@@ -56,8 +56,14 @@ typedef struct PACKED {
#define EECONFIG_KB_DATABLOCK ((uint8_t *)(EECONFIG_BASE_SIZE))
#define EECONFIG_USER_DATABLOCK ((uint8_t *)((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE)))
+#define EECONFIG_MODULES_DATABLOCK ((uint8_t *)((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE)))
+
+// Actual value is injected via the generated community_post_config.h
+#ifndef EECONFIG_MODULE_DATA_SIZE
+# define EECONFIG_MODULE_DATA_SIZE 0
+#endif
// Size of EEPROM being used, other code can refer to this for available EEPROM
-#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE))
+#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE) + (EECONFIG_MODULE_DATA_SIZE))
STATIC_ASSERT((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
diff --git a/quantum/painter/lvgl/qp_lvgl.c b/quantum/painter/lvgl/qp_lvgl.c
index dc639b5a366..2d8d96686c4 100644
--- a/quantum/painter/lvgl/qp_lvgl.c
+++ b/quantum/painter/lvgl/qp_lvgl.c
@@ -28,8 +28,11 @@ void qp_lvgl_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color
qp_viewport(selected_display, area->x1, area->y1, area->x2, area->y2);
qp_pixdata(selected_display, (void *)color_p, number_pixels);
qp_flush(selected_display);
- lv_disp_flush_ready(disp);
}
+ // Must always be signalled, even when there is no selected display:
+ // skipping it leaves LVGL's flush permanently "in progress" and stalls
+ // all further rendering.
+ lv_disp_flush_ready(disp);
}
static uint32_t tick_task_callback(uint32_t trigger_time, void *cb_arg) {
diff --git a/quantum/plover_hid.c b/quantum/plover_hid.c
new file mode 100644
index 00000000000..b7c3373754b
--- /dev/null
+++ b/quantum/plover_hid.c
@@ -0,0 +1,50 @@
+/* Copyright 2021 dnaq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include "plover_hid.h"
+#include "report.h"
+#include "host.h"
+#include "compiler_support.h"
+
+// Data field must hold a bit for every button in the range or the bit-packing below overflows.
+STATIC_ASSERT(sizeof(((report_plover_hid_t *)0)->data) * CHAR_BIT >= PLV_BTN_COUNT, "Plover HID report data too small for the button range");
+
+static report_plover_hid_t plover_hid_report = {.report_id = REPORT_ID_PLOVER_HID};
+static bool plover_hid_report_updated = false;
+
+void plover_hid_update(uint8_t button, bool pressed) {
+ if (button >= PLV_BTN_COUNT) {
+ return;
+ }
+
+ if (pressed) {
+ plover_hid_report.data[button / 8] |= (1 << (7 - (button % 8)));
+ } else {
+ plover_hid_report.data[button / 8] &= ~(1 << (7 - (button % 8)));
+ }
+ plover_hid_report_updated = true;
+}
+
+void plover_hid_task(void) {
+ if (!plover_hid_report_updated) {
+ return;
+ }
+
+ host_plover_hid_send(&plover_hid_report);
+ plover_hid_report_updated = false;
+}
diff --git a/quantum/plover_hid.h b/quantum/plover_hid.h
new file mode 100644
index 00000000000..a5ca7d89a0e
--- /dev/null
+++ b/quantum/plover_hid.h
@@ -0,0 +1,98 @@
+/* Copyright 2021 dnaq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+/**
+ * \enum plover_hid_button_t
+ *
+ * An enumeration of the possible Plover HID bit indexes.
+ *
+ * \note Index order is protocol-mandated and must match plover-machine-hid STENO_KEY_CHART position.
+ */
+typedef enum {
+ PLV_BTN_S1,
+ PLV_BTN_TL,
+ PLV_BTN_KL,
+ PLV_BTN_PL,
+ PLV_BTN_WL,
+ PLV_BTN_HL,
+ PLV_BTN_RL,
+ PLV_BTN_A,
+ PLV_BTN_O,
+ PLV_BTN_ST1,
+ PLV_BTN_E,
+ PLV_BTN_U,
+ PLV_BTN_FR,
+ PLV_BTN_RR,
+ PLV_BTN_PR,
+ PLV_BTN_BR,
+ PLV_BTN_LR,
+ PLV_BTN_GR,
+ PLV_BTN_TR,
+ PLV_BTN_SR,
+ PLV_BTN_DR,
+ PLV_BTN_ZR,
+ PLV_BTN_N1,
+ PLV_BTN_S2,
+ PLV_BTN_ST2,
+ PLV_BTN_ST3,
+ PLV_BTN_ST4,
+ PLV_BTN_N2,
+ PLV_BTN_N3,
+ PLV_BTN_N4,
+ PLV_BTN_N5,
+ PLV_BTN_N6,
+ PLV_BTN_N7,
+ PLV_BTN_N8,
+ PLV_BTN_N9,
+ PLV_BTN_NA,
+ PLV_BTN_NB,
+ PLV_BTN_NC,
+ PLV_BTN_X1,
+ PLV_BTN_X2,
+ PLV_BTN_X3,
+ PLV_BTN_X4,
+ PLV_BTN_X5,
+ PLV_BTN_X6,
+ PLV_BTN_X7,
+ PLV_BTN_X8,
+ PLV_BTN_X9,
+ PLV_BTN_X10,
+ PLV_BTN_X11,
+ PLV_BTN_X12,
+ PLV_BTN_X13,
+ PLV_BTN_X14,
+ PLV_BTN_X15,
+ PLV_BTN_X16,
+ PLV_BTN_X17,
+ PLV_BTN_X18,
+ PLV_BTN_X19,
+ PLV_BTN_X20,
+ PLV_BTN_X21,
+ PLV_BTN_X22,
+ PLV_BTN_X23,
+ PLV_BTN_X24,
+ PLV_BTN_X25,
+ PLV_BTN_X26,
+ PLV_BTN_COUNT, // Number of available buttons (always leave at the end)
+} plover_hid_button_t;
+
+void plover_hid_update(uint8_t button, bool pressed);
+void plover_hid_task(void);
diff --git a/quantum/process_keycode/process_key_lock.c b/quantum/process_keycode/process_key_lock.c
index 304a89c5cda..67a8186b572 100644
--- a/quantum/process_keycode/process_key_lock.c
+++ b/quantum/process_keycode/process_key_lock.c
@@ -57,7 +57,11 @@ static inline uint16_t translate_keycode(uint16_t keycode) {
void cancel_key_lock(void) {
watching = false;
- UNSET_KEY_STATE(0x0);
+ // Clear the full 256-bit state, otherwise every actually-locked key will still be latched.
+ key_state[0] = 0;
+ key_state[1] = 0;
+ key_state[2] = 0;
+ key_state[3] = 0;
}
bool process_key_lock(uint16_t *keycode, keyrecord_t *record) {
diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c
index 2b6e0dcf3d0..85e42d28fc8 100644
--- a/quantum/process_keycode/process_key_override.c
+++ b/quantum/process_keycode/process_key_override.c
@@ -441,6 +441,10 @@ bool process_key_override(const uint16_t keycode, const keyrecord_t *const recor
#ifdef KEY_OVERRIDE_INCLUDE_WEAK_MODS
effective_mods |= get_weak_mods();
+#elif defined(REPEAT_KEY_ENABLE)
+ if (get_repeat_key_count()) {
+ effective_mods |= get_weak_mods();
+ }
#endif
#ifndef NO_ACTION_ONESHOT
diff --git a/quantum/process_keycode/process_plover_hid.c b/quantum/process_keycode/process_plover_hid.c
new file mode 100644
index 00000000000..57a75bf7d7a
--- /dev/null
+++ b/quantum/process_keycode/process_plover_hid.c
@@ -0,0 +1,112 @@
+/* Copyright 2021 dnaq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "process_plover_hid.h"
+#include "plover_hid.h"
+#include "progmem.h"
+#include "util.h"
+#include "compiler_support.h"
+
+#define PLV_INVALID 0xFF
+
+// clang-format off
+static const uint8_t key_to_plover_hid[] PROGMEM = {
+ PLV_INVALID, // QK_STENO_FUNCTION - Ignore
+ PLV_BTN_N1, // QK_STENO_N1
+ PLV_BTN_N2, // QK_STENO_N2
+ PLV_BTN_N3, // QK_STENO_N3
+ PLV_BTN_N4, // QK_STENO_N4
+ PLV_BTN_N5, // QK_STENO_N5
+ PLV_BTN_N6, // QK_STENO_N6
+ PLV_BTN_S1, // QK_STENO_S1
+ PLV_BTN_S2, // QK_STENO_S2
+ PLV_BTN_TL, // QK_STENO_TL
+ PLV_BTN_KL, // QK_STENO_KL
+ PLV_BTN_PL, // QK_STENO_PL
+ PLV_BTN_WL, // QK_STENO_WL
+ PLV_BTN_HL, // QK_STENO_HL
+ PLV_BTN_RL, // QK_STENO_RL
+ PLV_BTN_A, // QK_STENO_A
+ PLV_BTN_O, // QK_STENO_O
+ PLV_BTN_ST1, // QK_STENO_ST1
+ PLV_BTN_ST2, // QK_STENO_ST2
+ PLV_INVALID, // QK_STENO_RESET1 - Ignore
+ PLV_INVALID, // QK_STENO_RESET2 - Ignore
+ PLV_INVALID, // QK_STENO_POWER - Ignore
+ PLV_BTN_ST3, // QK_STENO_ST3
+ PLV_BTN_ST4, // QK_STENO_ST4
+ PLV_BTN_E, // QK_STENO_E
+ PLV_BTN_U, // QK_STENO_U
+ PLV_BTN_FR, // QK_STENO_FR
+ PLV_BTN_RR, // QK_STENO_RR
+ PLV_BTN_PR, // QK_STENO_PR
+ PLV_BTN_BR, // QK_STENO_BR
+ PLV_BTN_LR, // QK_STENO_LR
+ PLV_BTN_GR, // QK_STENO_GR
+ PLV_BTN_TR, // QK_STENO_TR
+ PLV_BTN_SR, // QK_STENO_SR
+ PLV_BTN_DR, // QK_STENO_DR
+ PLV_BTN_N7, // QK_STENO_N7
+ PLV_BTN_N8, // QK_STENO_N8
+ PLV_BTN_N9, // QK_STENO_N9
+ PLV_BTN_NA, // QK_STENO_NA
+ PLV_BTN_NB, // QK_STENO_NB
+ PLV_BTN_NC, // QK_STENO_NC
+ PLV_BTN_ZR, // QK_STENO_ZR
+ PLV_BTN_X1, // QK_STENO_X1
+ PLV_BTN_X2, // QK_STENO_X2
+ PLV_BTN_X3, // QK_STENO_X3
+ PLV_BTN_X4, // QK_STENO_X4
+ PLV_BTN_X5, // QK_STENO_X5
+ PLV_BTN_X6, // QK_STENO_X6
+ PLV_BTN_X7, // QK_STENO_X7
+ PLV_BTN_X8, // QK_STENO_X8
+ PLV_BTN_X9, // QK_STENO_X9
+ PLV_BTN_X10, // QK_STENO_X10
+ PLV_BTN_X11, // QK_STENO_X11
+ PLV_BTN_X12, // QK_STENO_X12
+ PLV_BTN_X13, // QK_STENO_X13
+ PLV_BTN_X14, // QK_STENO_X14
+ PLV_BTN_X15, // QK_STENO_X15
+ PLV_BTN_X16, // QK_STENO_X16
+ PLV_BTN_X17, // QK_STENO_X17
+ PLV_BTN_X18, // QK_STENO_X18
+ PLV_BTN_X19, // QK_STENO_X19
+ PLV_BTN_X20, // QK_STENO_X20
+ PLV_BTN_X21, // QK_STENO_X21
+ PLV_BTN_X22, // QK_STENO_X22
+ PLV_BTN_X23, // QK_STENO_X23
+ PLV_BTN_X24, // QK_STENO_X24
+ PLV_BTN_X25, // QK_STENO_X25
+ PLV_BTN_X26, // QK_STENO_X26
+};
+// clang-format on
+
+STATIC_ASSERT(ARRAY_SIZE(key_to_plover_hid) == (QK_STENO_X26 - QK_STENO + 1), "key_to_plover_hid array size must match number of steno keys");
+
+bool process_plover_hid(uint16_t keycode, keyrecord_t *record) {
+ if (keycode < QK_STENO_FUNCTION || keycode > QK_STENO_X26) {
+ return true;
+ }
+
+ uint8_t button = pgm_read_byte(&key_to_plover_hid[keycode - QK_STENO]);
+ if (button == PLV_INVALID) {
+ return true;
+ }
+
+ plover_hid_update(button, record->event.pressed);
+ return false;
+}
diff --git a/keyboards/novelkeys/nk87/nk87.h b/quantum/process_keycode/process_plover_hid.h
old mode 100755
new mode 100644
similarity index 87%
rename from keyboards/novelkeys/nk87/nk87.h
rename to quantum/process_keycode/process_plover_hid.h
index 7f1a26c10e8..40472c7fee8
--- a/keyboards/novelkeys/nk87/nk87.h
+++ b/quantum/process_keycode/process_plover_hid.h
@@ -1,4 +1,4 @@
-/* Copyright 2020 Yiancar
+/* Copyright 2021 dnaq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,8 +13,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
#pragma once
#include "quantum.h"
-#include "../wilba_tech/wt_rgb_backlight_keycodes.h"
-#include "via.h"
+
+bool process_plover_hid(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_sequencer.c b/quantum/process_keycode/process_sequencer.c
index 6391d1ba9d5..44cc0243290 100644
--- a/quantum/process_keycode/process_sequencer.c
+++ b/quantum/process_keycode/process_sequencer.c
@@ -15,6 +15,8 @@
*/
#include "process_sequencer.h"
+#include "quantum_keycodes.h"
+#include "sequencer.h"
bool process_sequencer(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index 47894613523..90ce4620938 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -1,29 +1,24 @@
-/* Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include "process_steno.h"
-#include "quantum_keycodes.h"
-#include "eeconfig.h"
-#include
-#ifdef VIRTSER_ENABLE
-# include "virtser.h"
+#include "steno.h"
+#include "progmem.h"
+
+#ifdef STENO_ENABLE_BOLT
+void steno_add_key_to_chord_bolt(uint8_t chord[MAX_STROKE_SIZE], uint8_t key);
+void steno_send_chord_bolt(uint8_t chord[MAX_STROKE_SIZE]);
+#endif
+
+#ifdef STENO_ENABLE_GEMINI
+void steno_add_key_to_chord_gemini(uint8_t chord[MAX_STROKE_SIZE], uint8_t key);
+void steno_send_chord_gemini(uint8_t chord[MAX_STROKE_SIZE]);
#endif
// All steno keys that have been pressed to form this chord,
// stored in MAX_STROKE_SIZE groups of 8-bit arrays.
-static uint8_t chord[MAX_STROKE_SIZE] = {0};
+extern uint8_t steno_current_chord[MAX_STROKE_SIZE];
+
// The number of physical keys actually being held down.
// This is not always equal to the number of 1 bits in `chord` because it is possible to
// simultaneously press down four keys, then release three of those four keys and then press yet
@@ -32,109 +27,21 @@ static uint8_t chord[MAX_STROKE_SIZE] = {0};
// `n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down.
static int8_t n_pressed_keys = 0;
-#ifdef STENO_ENABLE_ALL
-static steno_mode_t mode;
-#elif defined(STENO_ENABLE_GEMINI)
-static const steno_mode_t mode = STENO_MODE_GEMINI;
-#elif defined(STENO_ENABLE_BOLT)
-static const steno_mode_t mode = STENO_MODE_BOLT;
-#endif
-
-static inline void steno_clear_chord(void) {
- memset(chord, 0, sizeof(chord));
-}
-
-#ifdef STENO_ENABLE_GEMINI
-
-# ifdef VIRTSER_ENABLE
-void send_steno_chord_gemini(void) {
- // Set MSB to 1 to indicate the start of packet
- chord[0] |= 0x80;
- for (uint8_t i = 0; i < GEMINI_STROKE_SIZE; ++i) {
- virtser_send(chord[i]);
- }
-}
-# else
-# pragma message "VIRTSER_ENABLE = yes is required for Gemini PR to work properly out of the box!"
-# endif // VIRTSER_ENABLE
-
-/**
- * @precondition: `key` is pressed
- */
-bool add_gemini_key_to_chord(uint8_t key) {
- // Although each group of the packet is 8 bits long, the MSB is reserved
- // to indicate whether that byte is the first byte of the packet (MSB=1)
- // or one of the remaining five bytes of the packet (MSB=0).
- // As a consequence, only 7 out of the 8 bits are left to be used as a bit array
- // for the steno keys of that group.
- const int group_idx = key / 7;
- const int intra_group_idx = key - group_idx * 7;
- // The 0th steno key of the group has bit=0b01000000, the 1st has bit=0b00100000, etc.
- const uint8_t bit = 1 << (6 - intra_group_idx);
- chord[group_idx] |= bit;
- return false;
-}
-#endif // STENO_ENABLE_GEMINI
-
-#ifdef STENO_ENABLE_BOLT
-
-# define TXB_GRP0 0b00000000
-# define TXB_GRP1 0b01000000
-# define TXB_GRP2 0b10000000
-# define TXB_GRP3 0b11000000
-# define TXB_GRPMASK 0b11000000
-
-# define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
-
-static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
-
-# ifdef VIRTSER_ENABLE
-static void send_steno_chord_bolt(void) {
- for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) {
- // TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys.
- // If a user chorded the keys of the first group with keys of the last group, for example, there
- // would be bytes of 0x00 in `chord` for the middle groups which we mustn't send.
- if (chord[i]) {
- virtser_send(chord[i]);
- }
- }
- // Sending a null packet is not always necessary, but it is simpler and more reliable
- // to unconditionally send it every time instead of keeping track of more states and
- // creating more branches in the execution of the program.
- virtser_send(0);
-}
-# else
-# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!"
-# endif // VIRTSER_ENABLE
-
-/**
- * @precondition: `key` is pressed
- */
-static bool add_bolt_key_to_chord(uint8_t key) {
- uint8_t boltcode = pgm_read_byte(boltmap + key);
- chord[TXB_GET_GROUP(boltcode)] |= boltcode;
- return false;
-}
-#endif // STENO_ENABLE_BOLT
-
#ifdef STENO_COMBINEDMAP
-/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
-static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
-static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
+// Used to look up when pressing the middle row key to combine two consonant or vowel keys
+static const uint16_t combinedmap_first[] PROGMEM = {QK_STENO_S1, QK_STENO_TL, QK_STENO_PL, QK_STENO_HL, QK_STENO_FR, QK_STENO_PR, QK_STENO_LR, QK_STENO_TR, QK_STENO_DR, QK_STENO_A, QK_STENO_E};
+static const uint16_t combinedmap_second[] PROGMEM = {QK_STENO_S2, QK_STENO_KL, QK_STENO_WL, QK_STENO_RL, QK_STENO_RR, QK_STENO_BR, QK_STENO_GR, QK_STENO_SR, QK_STENO_ZR, QK_STENO_O, QK_STENO_U};
+
+static bool process_steno_combinedmap(uint16_t keycode, keyrecord_t *record) {
+ uint16_t first_keycode = pgm_read_word(&combinedmap_first[keycode - QK_STENO_S3]);
+ uint16_t second_keycode = pgm_read_word(&combinedmap_second[keycode - QK_STENO_S3]);
+
+ bool first_result = process_steno(first_keycode, record);
+ bool second_result = process_steno(second_keycode, record);
+ return first_result && second_result;
+}
#endif
-#ifdef STENO_ENABLE_ALL
-void steno_init(void) {
- mode = eeconfig_read_steno_mode();
-}
-
-void steno_set_mode(steno_mode_t new_mode) {
- steno_clear_chord();
- mode = new_mode;
- eeconfig_update_steno_mode(mode);
-}
-#endif // STENO_ENABLE_ALL
-
/* override to intercept chords right before they get sent.
* return zero to suppress normal sending behavior.
*/
@@ -150,65 +57,97 @@ __attribute__((weak)) bool process_steno_user(uint16_t keycode, keyrecord_t *rec
return true;
}
-bool process_steno(uint16_t keycode, keyrecord_t *record) {
- if (keycode < QK_STENO || keycode > QK_STENO_MAX) {
- return true; // Not a steno key, pass it further along the chain
- /*
- * Clearing or sending the chord state is not necessary as we intentionally ignore whatever
- * normal keyboard keys the user may have tapped while chording steno keys.
- */
+static void steno_add_keycode_to_chord(uint16_t keycode) {
+ switch (steno_get_mode()) {
+#ifdef STENO_ENABLE_BOLT
+ case STENO_MODE_BOLT:
+ steno_add_key_to_chord_bolt(steno_current_chord, keycode - QK_STENO_FUNCTION);
+ break;
+#endif
+#ifdef STENO_ENABLE_GEMINI
+ case STENO_MODE_GEMINI:
+ steno_add_key_to_chord_gemini(steno_current_chord, keycode - QK_STENO_FUNCTION);
+ break;
+#endif
+ default:
+ break;
}
+}
+
+static void steno_send_chord(void) {
+ switch (steno_get_mode()) {
+#ifdef STENO_ENABLE_BOLT
+ case STENO_MODE_BOLT:
+ steno_send_chord_bolt(steno_current_chord);
+ break;
+#endif
+#ifdef STENO_ENABLE_GEMINI
+ case STENO_MODE_GEMINI:
+ steno_send_chord_gemini(steno_current_chord);
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+bool process_steno(uint16_t keycode, keyrecord_t *record) {
+ if (!IS_STENO_KEYCODE(keycode)) {
+ // Clearing or sending the chord state is not necessary as we intentionally ignore whatever
+ // normal keyboard keys the user may have tapped while chording steno keys.
+ return true; // pass keycode further along the chain
+ }
+
if (IS_NOEVENT(record->event)) {
return true;
}
+
if (!process_steno_user(keycode, record)) {
return false; // User fully processed the steno key themselves
}
+
switch (keycode) {
-#ifdef STENO_ENABLE_ALL
- case QK_STENO_BOLT:
+#if NUM_STENO_PROTOCOLS > 1
+ case QK_STENO_MODE_NEXT:
+ if (record->event.pressed) {
+ steno_mode_next();
+ }
+ return false;
+
+ case QK_STENO_MODE_PREVIOUS:
+ if (record->event.pressed) {
+ steno_mode_previous();
+ }
+ return false;
+
+ case QK_STENO_MODE_BOLT:
if (record->event.pressed) {
steno_set_mode(STENO_MODE_BOLT);
}
return false;
- case QK_STENO_GEMINI:
+ case QK_STENO_MODE_GEMINI:
if (record->event.pressed) {
steno_set_mode(STENO_MODE_GEMINI);
}
return false;
-#endif // STENO_ENABLE_ALL
+#endif
#ifdef STENO_COMBINEDMAP
- case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
- bool first_result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
- bool second_result = process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
- return first_result && second_result;
- }
-#endif // STENO_COMBINEDMAP
- case STN__MIN ... STN__MAX:
+ case QK_STENO_S3 ... QK_STENO_EU:
+ return process_steno_combinedmap(keycode, record);
+#endif
+
+ case QK_STENO_FUNCTION ... QK_STENO_ZR:
if (record->event.pressed) {
n_pressed_keys++;
- switch (mode) {
-#ifdef STENO_ENABLE_BOLT
- case STENO_MODE_BOLT:
- add_bolt_key_to_chord(keycode - QK_STENO);
- break;
-#endif // STENO_ENABLE_BOLT
-#ifdef STENO_ENABLE_GEMINI
- case STENO_MODE_GEMINI:
- add_gemini_key_to_chord(keycode - QK_STENO);
- break;
-#endif // STENO_ENABLE_GEMINI
- default:
- return false;
- }
- if (!post_process_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
+ steno_add_keycode_to_chord(keycode);
+ if (!post_process_steno_user(keycode, record, steno_get_mode(), steno_current_chord, n_pressed_keys)) {
return false;
}
} else { // is released
n_pressed_keys--;
- if (!post_process_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
+ if (!post_process_steno_user(keycode, record, steno_get_mode(), steno_current_chord, n_pressed_keys)) {
return false;
}
if (n_pressed_keys > 0) {
@@ -217,27 +156,17 @@ bool process_steno(uint16_t keycode, keyrecord_t *record) {
return false;
}
n_pressed_keys = 0;
- if (!send_steno_chord_user(mode, chord)) {
+ if (!send_steno_chord_user(steno_get_mode(), steno_current_chord)) {
steno_clear_chord();
return false;
}
- switch (mode) {
-#if defined(STENO_ENABLE_BOLT) && defined(VIRTSER_ENABLE)
- case STENO_MODE_BOLT:
- send_steno_chord_bolt();
- break;
-#endif // STENO_ENABLE_BOLT && VIRTSER_ENABLE
-#if defined(STENO_ENABLE_GEMINI) && defined(VIRTSER_ENABLE)
- case STENO_MODE_GEMINI:
- send_steno_chord_gemini();
- break;
-#endif // STENO_ENABLE_GEMINI && VIRTSER_ENABLE
- default:
- break;
- }
+ steno_send_chord();
steno_clear_chord();
}
+ return false;
+ default:
break;
}
+
return false;
}
diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h
index 5529980b719..b1e4e0dd00c 100644
--- a/quantum/process_keycode/process_steno.h
+++ b/quantum/process_keycode/process_steno.h
@@ -1,42 +1,10 @@
-/* Copyright 2017 Joseph Wasson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2017 Joseph Wasson
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include
#include
#include "action.h"
-#include "steno_keycodes.h"
-
-#define BOLT_STROKE_SIZE 4
-#define GEMINI_STROKE_SIZE 6
-
-#ifdef STENO_ENABLE_GEMINI
-# define MAX_STROKE_SIZE GEMINI_STROKE_SIZE
-#else
-# define MAX_STROKE_SIZE BOLT_STROKE_SIZE
-#endif
-
-typedef enum {
- STENO_MODE_GEMINI,
- STENO_MODE_BOLT,
-} steno_mode_t;
bool process_steno(uint16_t keycode, keyrecord_t *record);
-#ifdef STENO_ENABLE_ALL
-void steno_init(void);
-void steno_set_mode(steno_mode_t mode);
-#endif // STENO_ENABLE_ALL
diff --git a/quantum/quantum.c b/quantum/quantum.c
index be2e84f6d5e..196bb0534de 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -374,6 +374,9 @@ bool process_record_quantum(keyrecord_t *record) {
#if defined(LED_MATRIX_ENABLE)
process_led_matrix(keycode, record) &&
#endif
+#ifdef PLOVER_HID_ENABLE
+ process_plover_hid(keycode, record) &&
+#endif
#ifdef STENO_ENABLE
process_steno(keycode, record) &&
#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 176c8a292d8..f48f8dccda2 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -95,7 +95,12 @@ extern layer_state_t layer_state;
# endif
#endif
+#ifdef PLOVER_HID_ENABLE
+# include "process_plover_hid.h"
+#endif
+
#ifdef STENO_ENABLE
+# include "steno.h"
# include "process_steno.h"
#endif
diff --git a/quantum/repeat_key.c b/quantum/repeat_key.c
index bc385cb8948..bd7f01f3745 100644
--- a/quantum/repeat_key.c
+++ b/quantum/repeat_key.c
@@ -45,6 +45,10 @@ uint16_t get_last_keycode(void) {
return last_record.keycode;
}
+const keyrecord_t* get_last_record(void) {
+ return &last_record;
+}
+
uint8_t get_last_mods(void) {
return last_mods;
}
diff --git a/quantum/repeat_key.h b/quantum/repeat_key.h
index 9bfb6caed44..15a8c2cc777 100644
--- a/quantum/repeat_key.h
+++ b/quantum/repeat_key.h
@@ -26,7 +26,7 @@ void set_last_keycode(uint16_t keycode); /**< Sets the last key. */
void set_last_mods(uint8_t mods); /**< Sets the last mods. */
/** @brief Gets the record for the last key. */
-keyrecord_t* get_last_record(void);
+const keyrecord_t* get_last_record(void);
/** @brief Sets keycode and record info for the last key. */
void set_last_record(uint16_t keycode, keyrecord_t* record);
diff --git a/quantum/rgb_matrix/animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h
index 7d3b22f697a..2bd0a5f3e44 100644
--- a/quantum/rgb_matrix/animations/digital_rain_anim.h
+++ b/quantum/rgb_matrix/animations/digital_rain_anim.h
@@ -37,18 +37,22 @@ bool DIGITAL_RAIN(effect_params_t* params) {
g_rgb_frame_buffer[row][col]--;
}
}
+
// set the pixel colour
uint8_t led[LED_HITS_TO_REMEMBER];
uint8_t led_count = rgb_matrix_map_row_column_to_led(row, col, led);
- // TODO: multiple leds are supported mapped to the same row/column
if (led_count > 0) {
if (g_rgb_frame_buffer[row][col] > pure_green_intensity) {
const uint8_t boost = (uint8_t)((uint16_t)max_brightness_boost * (g_rgb_frame_buffer[row][col] - pure_green_intensity) / (max_intensity - pure_green_intensity));
- rgb_matrix_set_color(led[0], boost, max_intensity, boost);
+ for (uint8_t index = 0; index < led_count; index++) {
+ rgb_matrix_set_color(led[index], boost, max_intensity, boost);
+ }
} else {
const uint8_t green = (uint8_t)((uint16_t)max_intensity * g_rgb_frame_buffer[row][col] / pure_green_intensity);
- rgb_matrix_set_color(led[0], 0, green, 0);
+ for (uint8_t index = 0; index < led_count; index++) {
+ rgb_matrix_set_color(led[index], 0, green, 0);
+ }
}
}
}
diff --git a/quantum/rgb_matrix/animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index 77d79cf1af9..7f45d498591 100644
--- a/quantum/rgb_matrix/animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
@@ -77,19 +77,32 @@ bool TYPING_HEATMAP(effect_params_t* params) {
uint8_t count = 0;
for (uint8_t row = 0; row < MATRIX_ROWS && count < RGB_MATRIX_LED_PROCESS_LIMIT; row++) {
for (uint8_t col = 0; col < MATRIX_COLS && RGB_MATRIX_LED_PROCESS_LIMIT; col++) {
- if (g_led_config.matrix_co[row][col] >= led_min && g_led_config.matrix_co[row][col] < led_max) {
- count++;
- uint8_t val = g_rgb_frame_buffer[row][col];
- if (!HAS_ANY_FLAGS(g_led_config.flags[g_led_config.matrix_co[row][col]], params->flags)) continue;
+ uint8_t val = g_rgb_frame_buffer[row][col];
- hsv_t hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
- rgb_t rgb = rgb_matrix_hsv_to_rgb(hsv);
- rgb_matrix_set_color(g_led_config.matrix_co[row][col], rgb.r, rgb.g, rgb.b);
+ bool processed = false;
- if (decrease_heatmap_values) {
- g_rgb_frame_buffer[row][col] = qsub8(val, 1);
+ uint8_t led[LED_HITS_TO_REMEMBER];
+ uint8_t led_count = rgb_matrix_map_row_column_to_led(row, col, led);
+ for (uint8_t index = 0; index < led_count; index++) {
+ uint8_t led_index = led[index];
+
+ if (led_index >= led_min && led_index < led_max) {
+ count++;
+ if (!HAS_ANY_FLAGS(g_led_config.flags[led_index], params->flags)) {
+ continue;
+ }
+
+ hsv_t hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
+ rgb_t rgb = rgb_matrix_hsv_to_rgb(hsv);
+
+ rgb_matrix_set_color(led_index, rgb.r, rgb.g, rgb.b);
+ processed = true;
}
}
+
+ if (processed && decrease_heatmap_values) {
+ g_rgb_frame_buffer[row][col] = qsub8(val, 1);
+ }
}
}
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index e2b268efa7c..80f8d6fe11f 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -213,10 +213,10 @@ void rgb_matrix_handle_key_event(uint8_t row, uint8_t col, bool pressed) {
}
if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) {
- memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
- memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
- memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
- memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
+ memmove(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
+ memmove(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
last_hit_buffer.count = LED_HITS_TO_REMEMBER - led_count;
}
diff --git a/quantum/steno/steno.c b/quantum/steno/steno.c
new file mode 100644
index 00000000000..88623228836
--- /dev/null
+++ b/quantum/steno/steno.c
@@ -0,0 +1,126 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include
+#include
+#include
+#include "steno.h"
+#include "eeconfig.h"
+#include "util.h"
+#include "compiler_support.h"
+
+#ifndef STENO_DEFAULT_MODE
+# if defined(STENO_ENABLE_GEMINI)
+# define STENO_DEFAULT_MODE STENO_MODE_GEMINI
+# elif defined(STENO_ENABLE_BOLT)
+# define STENO_DEFAULT_MODE STENO_MODE_BOLT
+# endif
+#endif
+
+#if !defined(STENO_ENABLE_GEMINI)
+STATIC_ASSERT(STENO_DEFAULT_MODE != STENO_MODE_GEMINI, "STENO_DEFAULT_MODE is set to STENO_MODE_GEMINI, but is not available. Enable the geminipr protocol or change STENO_DEFAULT_MODE to a valid mode.");
+#endif
+#if !defined(STENO_ENABLE_BOLT)
+STATIC_ASSERT(STENO_DEFAULT_MODE != STENO_MODE_BOLT, "STENO_DEFAULT_MODE is set to STENO_MODE_BOLT, but is not available. Enable the txbolt protocol or change STENO_DEFAULT_MODE to a valid mode.");
+#endif
+
+static steno_mode_t mode = STENO_DEFAULT_MODE;
+
+uint8_t steno_current_chord[MAX_STROKE_SIZE] = {0};
+
+void steno_clear_chord(void) {
+ memset(steno_current_chord, 0, sizeof(steno_current_chord));
+}
+
+steno_mode_t steno_get_mode(void) {
+ return mode;
+}
+
+#if NUM_STENO_PROTOCOLS > 1
+
+static const steno_mode_t mode_candidates[] = {
+# if defined(STENO_ENABLE_GEMINI)
+ STENO_MODE_GEMINI,
+# endif
+# if defined(STENO_ENABLE_BOLT)
+ STENO_MODE_BOLT,
+# endif
+};
+
+# define MODE_CANDIDATES_COUNT ARRAY_SIZE(mode_candidates)
+
+static inline bool is_valid_mode(steno_mode_t mode) {
+ for (uint8_t i = 0; i < MODE_CANDIDATES_COUNT; i++) {
+ if (mode == mode_candidates[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void steno_set_mode_noeeprom(steno_mode_t new_mode) {
+ if (!is_valid_mode(new_mode)) {
+ return;
+ }
+
+ steno_clear_chord();
+
+ mode = new_mode;
+}
+
+void steno_set_mode(steno_mode_t new_mode) {
+ steno_set_mode_noeeprom(new_mode);
+
+ eeconfig_update_steno_mode(mode);
+}
+
+void steno_mode_next_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < MODE_CANDIDATES_COUNT; i++) {
+ if (mode_candidates[i] == mode) {
+ next = (i == MODE_CANDIDATES_COUNT - 1) ? 0 : (i + 1);
+ break;
+ }
+ }
+
+ steno_set_mode_noeeprom(mode_candidates[next]);
+}
+
+void steno_mode_next(void) {
+ steno_mode_next_noeeprom();
+
+ eeconfig_update_steno_mode(mode);
+}
+
+void steno_mode_previous_noeeprom(void) {
+ uint8_t next = 0;
+ for (uint8_t i = 0; i < MODE_CANDIDATES_COUNT; i++) {
+ if (mode_candidates[i] == mode) {
+ next = (i == 0) ? (MODE_CANDIDATES_COUNT - 1) : (i - 1);
+ break;
+ }
+ }
+
+ steno_set_mode_noeeprom(mode_candidates[next]);
+}
+
+void steno_mode_previous(void) {
+ steno_mode_previous_noeeprom();
+
+ eeconfig_update_steno_mode(mode);
+}
+
+#endif
+
+void eeconfig_update_steno_default(void) {
+ eeconfig_update_steno_mode(STENO_DEFAULT_MODE);
+}
+
+void steno_init(void) {
+#if NUM_STENO_PROTOCOLS > 1
+ steno_mode_t loaded = eeconfig_read_steno_mode();
+ if (is_valid_mode(loaded)) {
+ mode = loaded;
+ }
+#endif
+}
diff --git a/quantum/steno/steno.h b/quantum/steno/steno.h
new file mode 100644
index 00000000000..f9965e31b29
--- /dev/null
+++ b/quantum/steno/steno.h
@@ -0,0 +1,94 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include
+#include "steno_keycodes.h"
+
+#define BOLT_STROKE_SIZE 4
+#define GEMINI_STROKE_SIZE 6
+
+#if defined(STENO_ENABLE_GEMINI)
+# define MAX_STROKE_SIZE GEMINI_STROKE_SIZE
+#else
+# define MAX_STROKE_SIZE BOLT_STROKE_SIZE
+#endif
+
+/**
+ * \enum steno_mode_t
+ *
+ * An enumeration of the possible modes.
+ */
+typedef enum {
+ STENO_MODE_GEMINI,
+ STENO_MODE_BOLT,
+} steno_mode_t;
+
+/**
+ * \brief Initialize the subsystem.
+ *
+ * This function must be called only once, before any of the below functions can be called.
+ */
+void steno_init(void);
+
+/**
+ * \brief Reset configuration to defaults.
+ *
+ */
+void eeconfig_update_steno_default(void);
+
+/**
+ * \brief Clear any currently pressed chords.
+ *
+ */
+void steno_clear_chord(void);
+
+/**
+ * \brief Get currently configured mode.
+ *
+ * \return 'steno_mode_t' of the configured mode.
+ */
+steno_mode_t steno_get_mode(void);
+
+#if NUM_STENO_PROTOCOLS > 1
+
+/**
+ * \brief Set current mode. New state is not written to EEPROM.
+ *
+ * \param mode The mode to configure.
+ */
+void steno_set_mode_noeeprom(steno_mode_t mode);
+
+/**
+ * \brief Set current mode.
+ *
+ * \param mode The mode to configure.
+ */
+void steno_set_mode(steno_mode_t mode);
+
+/**
+ * \brief Move to the next potential mode. New state is not written to EEPROM.
+ *
+ */
+void steno_mode_next_noeeprom(void);
+
+/**
+ * \brief Move to the next potential mode.
+ *
+ */
+void steno_mode_next(void);
+
+/**
+ * \brief Move to the previous potential mode. New state is not written to EEPROM.
+ *
+ */
+void steno_mode_previous_noeeprom(void);
+
+/**
+ * \brief Move to the previous potential mode.
+ *
+ */
+void steno_mode_previous(void);
+
+#endif
diff --git a/quantum/steno/steno_bolt.c b/quantum/steno/steno_bolt.c
new file mode 100644
index 00000000000..0589026c883
--- /dev/null
+++ b/quantum/steno/steno_bolt.c
@@ -0,0 +1,113 @@
+// Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "steno.h"
+#include "progmem.h"
+#ifdef VIRTSER_ENABLE
+# include "virtser.h"
+#endif
+
+#define TXB_NUL 0
+#define TXB_S_L 0b00000001
+#define TXB_T_L 0b00000010
+#define TXB_K_L 0b00000100
+#define TXB_P_L 0b00001000
+#define TXB_W_L 0b00010000
+#define TXB_H_L 0b00100000
+#define TXB_R_L 0b01000001
+#define TXB_A_L 0b01000010
+#define TXB_O_L 0b01000100
+#define TXB_STR 0b01001000
+#define TXB_E_R 0b01010000
+#define TXB_U_R 0b01100000
+#define TXB_F_R 0b10000001
+#define TXB_R_R 0b10000010
+#define TXB_P_R 0b10000100
+#define TXB_B_R 0b10001000
+#define TXB_L_R 0b10010000
+#define TXB_G_R 0b10100000
+#define TXB_T_R 0b11000001
+#define TXB_S_R 0b11000010
+#define TXB_D_R 0b11000100
+#define TXB_Z_R 0b11001000
+#define TXB_NUM 0b11010000
+
+#define TXB_GRP0 0b00000000
+#define TXB_GRP1 0b01000000
+#define TXB_GRP2 0b10000000
+#define TXB_GRP3 0b11000000
+#define TXB_GRPMASK 0b11000000
+
+#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
+
+// clang-format off
+static const uint8_t boltmap[64] PROGMEM = {
+ TXB_NUL,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_S_L,
+ TXB_S_L,
+ TXB_T_L,
+ TXB_K_L,
+ TXB_P_L,
+ TXB_W_L,
+ TXB_H_L,
+ TXB_R_L,
+ TXB_A_L,
+ TXB_O_L,
+ TXB_STR,
+ TXB_STR,
+ TXB_NUL,
+ TXB_NUL,
+ TXB_NUL,
+ TXB_STR,
+ TXB_STR,
+ TXB_E_R,
+ TXB_U_R,
+ TXB_F_R,
+ TXB_R_R,
+ TXB_P_R,
+ TXB_B_R,
+ TXB_L_R,
+ TXB_G_R,
+ TXB_T_R,
+ TXB_S_R,
+ TXB_D_R,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_NUM,
+ TXB_Z_R,
+};
+// clang-format on
+
+void steno_add_key_to_chord_bolt(uint8_t chord[MAX_STROKE_SIZE], uint8_t key) {
+ uint8_t boltcode = pgm_read_byte(boltmap + key);
+
+ chord[TXB_GET_GROUP(boltcode)] |= boltcode;
+}
+
+void steno_send_chord_bolt(uint8_t chord[MAX_STROKE_SIZE]) {
+#ifdef VIRTSER_ENABLE
+ for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) {
+ // TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys.
+ // If a user chorded the keys of the first group with keys of the last group, for example, there
+ // would be bytes of 0x00 in `chord` for the middle groups which we mustn't send.
+ if (chord[i]) {
+ virtser_send(chord[i]);
+ }
+ }
+ // Sending a null packet is not always necessary, but it is simpler and more reliable
+ // to unconditionally send it every time instead of keeping track of more states and
+ // creating more branches in the execution of the program.
+ virtser_send(0);
+#else
+# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!"
+#endif // VIRTSER_ENABLE
+}
diff --git a/quantum/steno/steno_gemini.c b/quantum/steno/steno_gemini.c
new file mode 100644
index 00000000000..78e69fac903
--- /dev/null
+++ b/quantum/steno/steno_gemini.c
@@ -0,0 +1,32 @@
+// Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "steno.h"
+#ifdef VIRTSER_ENABLE
+# include "virtser.h"
+#endif
+
+void steno_add_key_to_chord_gemini(uint8_t chord[MAX_STROKE_SIZE], uint8_t key) {
+ // Although each group of the packet is 8 bits long, the MSB is reserved
+ // to indicate whether that byte is the first byte of the packet (MSB=1)
+ // or one of the remaining five bytes of the packet (MSB=0).
+ // As a consequence, only 7 out of the 8 bits are left to be used as a bit array
+ // for the steno keys of that group.
+ const int group_idx = key / 7;
+ const int intra_group_idx = key - group_idx * 7;
+ // The 0th steno key of the group has bit=0b01000000, the 1st has bit=0b00100000, etc.
+ const uint8_t bit = 1 << (6 - intra_group_idx);
+ chord[group_idx] |= bit;
+}
+
+void steno_send_chord_gemini(uint8_t chord[MAX_STROKE_SIZE]) {
+#ifdef VIRTSER_ENABLE
+ // Set MSB to 1 to indicate the start of packet
+ chord[0] |= 0x80;
+ for (uint8_t i = 0; i < GEMINI_STROKE_SIZE; ++i) {
+ virtser_send(chord[i]);
+ }
+#else
+# pragma message "VIRTSER_ENABLE = yes is required for Gemini PR to work properly out of the box!"
+#endif // VIRTSER_ENABLE
+}
diff --git a/quantum/steno_keycodes.h b/quantum/steno_keycodes.h
index 852b2f71211..eee28f0c248 100644
--- a/quantum/steno_keycodes.h
+++ b/quantum/steno_keycodes.h
@@ -1,119 +1,71 @@
-/* Copyright 2017 Joseph Wasson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "keycodes.h"
-// List of keycodes for the steno keyboard. To prevent
-// errors, this must be <= 42 total entries in order to
-// support the GeminiPR protocol.
-enum steno_keycodes {
- STN__MIN = QK_STENO,
- STN_FN = STN__MIN,
- STN_NUM,
- STN_N1 = STN_NUM,
- STN_N2,
- STN_N3,
- STN_N4,
- STN_N5,
- STN_N6,
- STN_SL,
- STN_S1 = STN_SL,
- STN_S2,
- STN_TL,
- STN_KL,
- STN_PL,
- STN_WL,
- STN_HL,
- STN_RL,
- STN_A,
- STN_O,
- STN_STR,
- STN_ST1 = STN_STR,
- STN_ST2,
- STN_RES1,
- STN_RE1 = STN_RES1,
- STN_RES2,
- STN_RE2 = STN_RES2,
- STN_PWR,
- STN_ST3,
- STN_ST4,
- STN_E,
- STN_U,
- STN_FR,
- STN_RR,
- STN_PR,
- STN_BR,
- STN_LR,
- STN_GR,
- STN_TR,
- STN_SR,
- STN_DR,
- STN_N7,
- STN_N8,
- STN_N9,
- STN_NA,
- STN_NB,
- STN_NC,
- STN_ZR,
- STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT
-};
+// Deprecated steno keycodes
+#define STN_FN QK_STENO_FUNCTION
+#define STN_N1 QK_STENO_N1
+#define STN_N2 QK_STENO_N2
+#define STN_N3 QK_STENO_N3
+#define STN_N4 QK_STENO_N4
+#define STN_N5 QK_STENO_N5
+#define STN_N6 QK_STENO_N6
+#define STN_S1 QK_STENO_S1
+#define STN_S2 QK_STENO_S2
+#define STN_TL QK_STENO_TL
+#define STN_KL QK_STENO_KL
+#define STN_PL QK_STENO_PL
+#define STN_WL QK_STENO_WL
+#define STN_HL QK_STENO_HL
+#define STN_RL QK_STENO_RL
+#define STN_A QK_STENO_A
+#define STN_O QK_STENO_O
+#define STN_ST1 QK_STENO_ST1
+#define STN_ST2 QK_STENO_ST2
+#define STN_RE1 QK_STENO_RESET1
+#define STN_RE2 QK_STENO_RESET2
+#define STN_PWR QK_STENO_POWER
+#define STN_ST3 QK_STENO_ST3
+#define STN_ST4 QK_STENO_ST4
+#define STN_E QK_STENO_E
+#define STN_U QK_STENO_U
+#define STN_FR QK_STENO_FR
+#define STN_RR QK_STENO_RR
+#define STN_PR QK_STENO_PR
+#define STN_BR QK_STENO_BR
+#define STN_LR QK_STENO_LR
+#define STN_GR QK_STENO_GR
+#define STN_TR QK_STENO_TR
+#define STN_SR QK_STENO_SR
+#define STN_DR QK_STENO_DR
+#define STN_N7 QK_STENO_N7
+#define STN_N8 QK_STENO_N8
+#define STN_N9 QK_STENO_N9
+#define STN_NA QK_STENO_NA
+#define STN_NB QK_STENO_NB
+#define STN_NC QK_STENO_NC
+#define STN_ZR QK_STENO_ZR
-#ifdef STENO_COMBINEDMAP
-enum steno_combined_keycodes {
- STN_S3 = QK_STENO_COMB,
- STN_TKL,
- STN_PWL,
- STN_HRL,
- STN_FRR,
- STN_PBR,
- STN_LGR,
- STN_TSR,
- STN_DZR,
- STN_AO,
- STN_EU,
- STN_COMB_MAX = STN_EU,
-};
-#endif
+#define STN_NUM QK_STENO_N1
+#define STN_SL QK_STENO_S1
+#define STN_STR QK_STENO_ST1
+#define STN_RES1 QK_STENO_RESET1
+#define STN_RES2 QK_STENO_RESET2
-#ifdef STENO_ENABLE_BOLT
-// TxBolt Codes
-# define TXB_NUL 0
-# define TXB_S_L 0b00000001
-# define TXB_T_L 0b00000010
-# define TXB_K_L 0b00000100
-# define TXB_P_L 0b00001000
-# define TXB_W_L 0b00010000
-# define TXB_H_L 0b00100000
-# define TXB_R_L 0b01000001
-# define TXB_A_L 0b01000010
-# define TXB_O_L 0b01000100
-# define TXB_STR 0b01001000
-# define TXB_E_R 0b01010000
-# define TXB_U_R 0b01100000
-# define TXB_F_R 0b10000001
-# define TXB_R_R 0b10000010
-# define TXB_P_R 0b10000100
-# define TXB_B_R 0b10001000
-# define TXB_L_R 0b10010000
-# define TXB_G_R 0b10100000
-# define TXB_T_R 0b11000001
-# define TXB_S_R 0b11000010
-# define TXB_D_R 0b11000100
-# define TXB_Z_R 0b11001000
-# define TXB_NUM 0b11010000
-#endif // STENO_ENABLE_BOLT
+#define STN_S3 QK_STENO_S3
+#define STN_TKL QK_STENO_TKL
+#define STN_PWL QK_STENO_PWL
+#define STN_HRL QK_STENO_HRL
+#define STN_FRR QK_STENO_FRR
+#define STN_PBR QK_STENO_PBR
+#define STN_LGR QK_STENO_LGR
+#define STN_TSR QK_STENO_TSR
+#define STN_DZR QK_STENO_DZR
+#define STN_AO QK_STENO_AO
+#define STN_EU QK_STENO_EU
+
+#define QK_STENO_BOLT QK_STENO_MODE_BOLT
+#define QK_STENO_GEMINI QK_STENO_MODE_GEMINI
diff --git a/tests/pointing/azoteq_iqs5xx/azoteq_iqs5xx_mock.c b/tests/pointing/azoteq_iqs5xx/azoteq_iqs5xx_mock.c
new file mode 100644
index 00000000000..ef59d582aed
--- /dev/null
+++ b/tests/pointing/azoteq_iqs5xx/azoteq_iqs5xx_mock.c
@@ -0,0 +1,45 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include
+
+#include "azoteq_iqs5xx.h"
+
+static azoteq_iqs5xx_base_data_t mock_base_data;
+static i2c_status_t mock_read_status = I2C_STATUS_SUCCESS;
+
+void azoteq_iqs5xx_mock_reset(void) {
+ memset(&mock_base_data, 0, sizeof(mock_base_data));
+ mock_read_status = I2C_STATUS_SUCCESS;
+}
+
+void azoteq_iqs5xx_mock_set_base_data(azoteq_iqs5xx_base_data_t base_data) {
+ mock_base_data = base_data;
+ mock_read_status = I2C_STATUS_SUCCESS;
+}
+
+void i2c_init(void) {}
+
+i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
+ return I2C_STATUS_SUCCESS;
+}
+
+i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t *data, uint16_t length, uint16_t timeout) {
+ if (mock_read_status == I2C_STATUS_SUCCESS && data != NULL) {
+ memcpy(data, &mock_base_data, MIN(length, sizeof(mock_base_data)));
+ }
+ return mock_read_status;
+}
+
+i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t *data, uint16_t length, uint16_t timeout) {
+ return I2C_STATUS_SUCCESS;
+}
+
+uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
+ if (pressed) {
+ buttons |= 1 << button;
+ } else {
+ buttons &= ~(1 << button);
+ }
+ return buttons;
+}
diff --git a/tests/pointing/azoteq_iqs5xx/config.h b/tests/pointing/azoteq_iqs5xx/config.h
new file mode 100644
index 00000000000..efcf73c8d63
--- /dev/null
+++ b/tests/pointing/azoteq_iqs5xx/config.h
@@ -0,0 +1,8 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "test_common.h"
+
+#define AZOTEQ_IQS5XX_TPS43
diff --git a/tests/pointing/azoteq_iqs5xx/test.mk b/tests/pointing/azoteq_iqs5xx/test.mk
new file mode 100644
index 00000000000..2bcf61ca2ea
--- /dev/null
+++ b/tests/pointing/azoteq_iqs5xx/test.mk
@@ -0,0 +1,8 @@
+# Copyright 2026 QMK
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+SRC += drivers/sensors/azoteq_iqs5xx.c
+SRC += tests/pointing/azoteq_iqs5xx/azoteq_iqs5xx_mock.c
+
+VPATH += $(QUANTUM_DIR)/pointing_device
+VPATH += drivers/sensors
diff --git a/tests/pointing/azoteq_iqs5xx/test_azoteq_iqs5xx.cpp b/tests/pointing/azoteq_iqs5xx/test_azoteq_iqs5xx.cpp
new file mode 100644
index 00000000000..1e8b85a2af1
--- /dev/null
+++ b/tests/pointing/azoteq_iqs5xx/test_azoteq_iqs5xx.cpp
@@ -0,0 +1,54 @@
+// Copyright 2026 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "gtest/gtest.h"
+
+extern "C" {
+#include "azoteq_iqs5xx.h"
+
+void azoteq_iqs5xx_mock_reset(void);
+void azoteq_iqs5xx_mock_set_base_data(azoteq_iqs5xx_base_data_t base_data);
+}
+
+class AzoteqIqs5xx : public testing::Test {
+ protected:
+ void SetUp() override {
+ azoteq_iqs5xx_mock_reset();
+ }
+};
+
+TEST_F(AzoteqIqs5xx, PreservesIncomingButtonsWhenReportingMovement) {
+ azoteq_iqs5xx_base_data_t base_data = {0};
+ base_data.number_of_fingers = 1;
+ base_data.x.l = 12;
+ base_data.y.l = 34;
+ azoteq_iqs5xx_mock_set_base_data(base_data);
+
+ report_mouse_t input_report = {0};
+ input_report.buttons = (1 << POINTING_DEVICE_BUTTON1) | (1 << POINTING_DEVICE_BUTTON2);
+
+ report_mouse_t report = azoteq_iqs5xx_get_report(input_report);
+
+ EXPECT_EQ(report.x, 12);
+ EXPECT_EQ(report.y, 34);
+ EXPECT_EQ(report.h, 0);
+ EXPECT_EQ(report.v, 0);
+ EXPECT_EQ(report.buttons, input_report.buttons);
+}
+
+TEST_F(AzoteqIqs5xx, CombinesGestureButtonWithIncomingButtons) {
+ azoteq_iqs5xx_base_data_t base_data = {0};
+ base_data.gesture_events_1.two_finger_tap = true;
+ azoteq_iqs5xx_mock_set_base_data(base_data);
+
+ report_mouse_t input_report = {0};
+ input_report.buttons = 1 << POINTING_DEVICE_BUTTON1;
+
+ report_mouse_t report = azoteq_iqs5xx_get_report(input_report);
+
+ EXPECT_EQ(report.x, 0);
+ EXPECT_EQ(report.y, 0);
+ EXPECT_EQ(report.h, 0);
+ EXPECT_EQ(report.v, 0);
+ EXPECT_EQ(report.buttons, input_report.buttons | (1 << POINTING_DEVICE_BUTTON2));
+}
diff --git a/tests/repeat_key/repeat_key_overrides/config.h b/tests/repeat_key/repeat_key_overrides/config.h
new file mode 100644
index 00000000000..5a99fe50c28
--- /dev/null
+++ b/tests/repeat_key/repeat_key_overrides/config.h
@@ -0,0 +1,17 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "test_common.h"
diff --git a/tests/repeat_key/repeat_key_overrides/test.mk b/tests/repeat_key/repeat_key_overrides/test.mk
new file mode 100644
index 00000000000..adda6c0b8c4
--- /dev/null
+++ b/tests/repeat_key/repeat_key_overrides/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2026 Google LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+REPEAT_KEY_ENABLE = yes
+KEY_OVERRIDE_ENABLE = yes
+INTROSPECTION_KEYMAP_C = test_keymap.c
diff --git a/tests/repeat_key/repeat_key_overrides/test_keymap.c b/tests/repeat_key/repeat_key_overrides/test_keymap.c
new file mode 100644
index 00000000000..171f47e50e4
--- /dev/null
+++ b/tests/repeat_key/repeat_key_overrides/test_keymap.c
@@ -0,0 +1,19 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "quantum.h"
+
+const key_override_t alt_slash_override = ko_make_basic(MOD_BIT(KC_LALT), KC_SLSH, KC_BSLS);
+
+const key_override_t *key_overrides[] = {&alt_slash_override, NULL};
diff --git a/tests/repeat_key/repeat_key_overrides/test_repeat_key_overrides.cpp b/tests/repeat_key/repeat_key_overrides/test_repeat_key_overrides.cpp
new file mode 100644
index 00000000000..5058ff69551
--- /dev/null
+++ b/tests/repeat_key/repeat_key_overrides/test_repeat_key_overrides.cpp
@@ -0,0 +1,190 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using ::testing::AnyNumber;
+using ::testing::Matcher;
+
+namespace {
+
+bool process_record_user_default(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+bool remember_last_key_user_default(uint16_t keycode, keyrecord_t *record, uint8_t *remembered_mods) {
+ return true;
+}
+
+std::function process_record_user_fun = process_record_user_default;
+std::function remember_last_key_user_fun = remember_last_key_user_default;
+
+extern "C" bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ return process_record_user_fun(keycode, record);
+}
+
+extern "C" bool remember_last_key_user(uint16_t keycode, keyrecord_t *record, uint8_t *remembered_mods) {
+ return remember_last_key_user_fun(keycode, record, remembered_mods);
+}
+
+class RepeatKeyOverrides : public TestFixture {
+ public:
+ bool process_record_user_was_called_;
+
+ void SetUp() override {
+ reset_repeat_key_state();
+ process_record_user_fun = process_record_user_default;
+ remember_last_key_user_fun = remember_last_key_user_default;
+ }
+
+ void ExpectProcessRecordUserCalledWith(bool expected_press, uint16_t expected_keycode, int8_t expected_repeat_key_count) {
+ process_record_user_was_called_ = false;
+ process_record_user_fun = [=](uint16_t keycode, keyrecord_t *record) {
+ EXPECT_EQ(record->event.pressed, expected_press);
+ EXPECT_KEYCODE_EQ(keycode, expected_keycode);
+ EXPECT_EQ(get_repeat_key_count(), expected_repeat_key_count);
+ process_record_user_was_called_ = true;
+ return true;
+ };
+ }
+};
+
+// Tests that pressing Left Alt + / triggers override to backslash \,
+// and tapping Repeat Key subsequently outputs \ again.
+TEST_F(RepeatKeyOverrides, AltSlashOverride) {
+ TestDriver driver;
+ Matcher empty_or_lalt = AnyOf(KeyboardReport(), KeyboardReport(KC_LALT));
+ KeymapKey key_lalt(0, 0, 0, KC_LALT);
+ KeymapKey key_slsh(0, 1, 0, KC_SLSH);
+ KeymapKey key_repeat(0, 2, 0, QK_REP);
+ set_keymap({key_lalt, key_slsh, key_repeat});
+
+ // Hold Left Alt
+ EXPECT_REPORT(driver, (KC_LALT));
+ key_lalt.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Press / (triggers override -> backslash \, Left Alt suppressed)
+ EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_BSLS));
+ key_slsh.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Release / (Left Alt still held, so Left Alt is sent again)
+ EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_LALT));
+ key_slsh.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Release Left Alt
+ EXPECT_EMPTY_REPORT(driver);
+ key_lalt.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Tap Repeat Key (sends \, since weak Left Alt + / triggers override)
+ EXPECT_CALL(driver, send_keyboard_mock(empty_or_lalt)).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_BSLS));
+ ExpectProcessRecordUserCalledWith(true, KC_SLSH, 1);
+ key_repeat.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(process_record_user_was_called_);
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(empty_or_lalt)).Times(AnyNumber());
+ ExpectProcessRecordUserCalledWith(false, KC_SLSH, 1);
+ key_repeat.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(process_record_user_was_called_);
+ VERIFY_AND_CLEAR(driver);
+}
+
+// Tests that pressing Left Alt + Left Shift + / triggers override to |,
+// and tapping Repeat Key subsequently outputs | again.
+TEST_F(RepeatKeyOverrides, AltShiftSlashOverride) {
+ TestDriver driver;
+ Matcher lsft_and_or_lalt = AnyOf(KeyboardReport(KC_LSFT), KeyboardReport(KC_LSFT, KC_LALT));
+ KeymapKey key_lalt(0, 0, 0, KC_LALT);
+ KeymapKey key_lshift(0, 1, 0, KC_LSFT);
+ KeymapKey key_slsh(0, 2, 0, KC_SLSH);
+ KeymapKey key_repeat(0, 3, 0, QK_REP);
+ set_keymap({key_lalt, key_lshift, key_slsh, key_repeat});
+
+ // Hold Left Alt
+ EXPECT_REPORT(driver, (KC_LALT));
+ key_lalt.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Hold Left Shift
+ EXPECT_REPORT(driver, (KC_LALT, KC_LSFT));
+ key_lshift.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Press / (triggers override -> Shift + \, Alt suppressed, Shift remains)
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_LSFT, KC_BSLS));
+ key_slsh.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Release /
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_LALT, KC_LSFT));
+ key_slsh.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Release Left Shift
+ EXPECT_EMPTY_REPORT(driver).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_LALT));
+ key_lshift.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Release Left Alt
+ EXPECT_EMPTY_REPORT(driver);
+ key_lalt.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ // Tap Repeat Key (sends | -> Shift + \)
+ EXPECT_CALL(driver, send_keyboard_mock(lsft_and_or_lalt)).Times(AnyNumber());
+ EXPECT_REPORT(driver, (KC_LSFT, KC_BSLS));
+ ExpectProcessRecordUserCalledWith(true, KC_SLSH, 1);
+ key_repeat.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(process_record_user_was_called_);
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(lsft_and_or_lalt)).Times(AnyNumber());
+ EXPECT_EMPTY_REPORT(driver);
+ ExpectProcessRecordUserCalledWith(false, KC_SLSH, 1);
+ key_repeat.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(process_record_user_was_called_);
+ VERIFY_AND_CLEAR(driver);
+}
+
+} // namespace
diff --git a/tmk_core/protocol/chibios/usb_driver.c b/tmk_core/protocol/chibios/usb_driver.c
index 8b471cba563..15904155a78 100644
--- a/tmk_core/protocol/chibios/usb_driver.c
+++ b/tmk_core/protocol/chibios/usb_driver.c
@@ -320,13 +320,13 @@ bool usb_endpoint_in_is_inactive(usb_endpoint_in_t *endpoint) {
return inactive;
}
-bool usb_endpoint_out_receive(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout) {
+size_t usb_endpoint_out_receive_bytes(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout) {
osalDbgCheck((endpoint != NULL) && (data != NULL) && (size > 0U));
osalSysLock();
if (usbGetDriverStateI(endpoint->config.usbp) != USB_ACTIVE) {
osalSysUnlock();
- return false;
+ return 0;
}
if (endpoint->timed_out && timeout != TIME_INFINITE) {
@@ -337,5 +337,9 @@ bool usb_endpoint_out_receive(usb_endpoint_out_t *endpoint, uint8_t *data, size_
const size_t received = ibqReadTimeout(&endpoint->ibqueue, data, size, timeout);
endpoint->timed_out = received == 0;
- return received == size;
+ return received;
+}
+
+bool usb_endpoint_out_receive(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout) {
+ return usb_endpoint_out_receive_bytes(endpoint, data, size, timeout) == size;
}
diff --git a/tmk_core/protocol/chibios/usb_driver.h b/tmk_core/protocol/chibios/usb_driver.h
index 26787e1eba0..b3a3e5f8906 100644
--- a/tmk_core/protocol/chibios/usb_driver.h
+++ b/tmk_core/protocol/chibios/usb_driver.h
@@ -24,6 +24,8 @@
NULL, /* SETUP buffer (not a SETUP endpoint) */
#endif
+#define EPSIZE_ALIGN(n) (((n) + 3) & ~3)
+
/*
* Implementation notes:
*
@@ -33,96 +35,96 @@
* Given `USBv1/hal_usb_lld.h` marks the field as "not currently used" this code file
* makes the assumption this is safe to avoid littering with preprocessor directives.
*/
-#define QMK_USB_ENDPOINT_IN(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \
- { \
- .usb_requests_cb = _usb_requests_cb, .report_storage = _report_storage, \
- .ep_config = \
- { \
- mode, /* EP Mode */ \
- NULL, /* SETUP packet notification callback */ \
- usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \
- NULL, /* OUT notification callback */ \
- ep_size, /* IN maximum packet size */ \
- 0, /* OUT maximum packet size */ \
- NULL, /* IN Endpoint state */ \
- NULL, /* OUT endpoint state */ \
- usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
- }, \
- .config = { \
- .usbp = &USB_DRIVER, \
- .ep = ep_num, \
- .buffer_capacity = _buffer_capacity, \
- .buffer_size = ep_size, \
- .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0}, \
- } \
+#define QMK_USB_ENDPOINT_IN(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \
+ { \
+ .usb_requests_cb = _usb_requests_cb, .report_storage = _report_storage, \
+ .ep_config = \
+ { \
+ mode, /* EP Mode */ \
+ NULL, /* SETUP packet notification callback */ \
+ usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \
+ NULL, /* OUT notification callback */ \
+ ep_size, /* IN maximum packet size */ \
+ 0, /* OUT maximum packet size */ \
+ NULL, /* IN Endpoint state */ \
+ NULL, /* OUT endpoint state */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
+ }, \
+ .config = { \
+ .usbp = &USB_DRIVER, \
+ .ep = ep_num, \
+ .buffer_capacity = _buffer_capacity, \
+ .buffer_size = EPSIZE_ALIGN(ep_size), \
+ .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0}, \
+ } \
}
#if !defined(USB_ENDPOINTS_ARE_REORDERABLE)
-# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \
- { \
- .ep_config = \
- { \
- mode, /* EP Mode */ \
- NULL, /* SETUP packet notification callback */ \
- NULL, /* IN notification callback */ \
- usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \
- 0, /* IN maximum packet size */ \
- ep_size, /* OUT maximum packet size */ \
- NULL, /* IN Endpoint state */ \
- NULL, /* OUT endpoint state */ \
- usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
- }, \
- .config = { \
- .usbp = &USB_DRIVER, \
- .ep = ep_num, \
- .buffer_capacity = _buffer_capacity, \
- .buffer_size = ep_size, \
- .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0} \
- } \
+# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \
+ { \
+ .ep_config = \
+ { \
+ mode, /* EP Mode */ \
+ NULL, /* SETUP packet notification callback */ \
+ NULL, /* IN notification callback */ \
+ usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \
+ 0, /* IN maximum packet size */ \
+ ep_size, /* OUT maximum packet size */ \
+ NULL, /* IN Endpoint state */ \
+ NULL, /* OUT endpoint state */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
+ }, \
+ .config = { \
+ .usbp = &USB_DRIVER, \
+ .ep = ep_num, \
+ .buffer_capacity = _buffer_capacity, \
+ .buffer_size = EPSIZE_ALIGN(ep_size), \
+ .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0} \
+ } \
}
#else
-# define QMK_USB_ENDPOINT_IN_SHARED(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \
- { \
- .usb_requests_cb = _usb_requests_cb, .is_shared = true, .report_storage = _report_storage, \
- .ep_config = \
- { \
- mode, /* EP Mode */ \
- NULL, /* SETUP packet notification callback */ \
- usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \
- usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \
- ep_size, /* IN maximum packet size */ \
- ep_size, /* OUT maximum packet size */ \
- NULL, /* IN Endpoint state */ \
- NULL, /* OUT endpoint state */ \
- usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
- }, \
- .config = { \
- .usbp = &USB_DRIVER, \
- .ep = ep_num, \
- .buffer_capacity = _buffer_capacity, \
- .buffer_size = ep_size, \
- .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0}, \
- } \
+# define QMK_USB_ENDPOINT_IN_SHARED(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \
+ { \
+ .usb_requests_cb = _usb_requests_cb, .is_shared = true, .report_storage = _report_storage, \
+ .ep_config = \
+ { \
+ mode, /* EP Mode */ \
+ NULL, /* SETUP packet notification callback */ \
+ usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \
+ usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \
+ ep_size, /* IN maximum packet size */ \
+ ep_size, /* OUT maximum packet size */ \
+ NULL, /* IN Endpoint state */ \
+ NULL, /* OUT endpoint state */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
+ }, \
+ .config = { \
+ .usbp = &USB_DRIVER, \
+ .ep = ep_num, \
+ .buffer_capacity = _buffer_capacity, \
+ .buffer_size = EPSIZE_ALIGN(ep_size), \
+ .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0}, \
+ } \
}
/* The current assumption is that there are no standalone OUT endpoints, so the
* OUT endpoint is always initialized by the IN endpoint. */
-# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \
- { \
- .ep_config = \
- { \
- 0 /* Already defined in the IN endpoint */ \
- }, \
- .config = { \
- .usbp = &USB_DRIVER, \
- .ep = ep_num, \
- .buffer_capacity = _buffer_capacity, \
- .buffer_size = ep_size, \
- .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0} \
- } \
+# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \
+ { \
+ .ep_config = \
+ { \
+ 0 /* Already defined in the IN endpoint */ \
+ }, \
+ .config = { \
+ .usbp = &USB_DRIVER, \
+ .ep = ep_num, \
+ .buffer_capacity = _buffer_capacity, \
+ .buffer_size = EPSIZE_ALIGN(ep_size), \
+ .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0} \
+ } \
}
#endif
@@ -197,7 +199,8 @@ void usb_endpoint_out_init(usb_endpoint_out_t *endpoint);
void usb_endpoint_out_start(usb_endpoint_out_t *endpoint);
void usb_endpoint_out_stop(usb_endpoint_out_t *endpoint);
-bool usb_endpoint_out_receive(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout);
+bool usb_endpoint_out_receive(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout);
+size_t usb_endpoint_out_receive_bytes(usb_endpoint_out_t *endpoint, uint8_t *data, size_t size, sysinterval_t timeout);
void usb_endpoint_out_suspend_cb(usb_endpoint_out_t *endpoint);
void usb_endpoint_out_wakeup_cb(usb_endpoint_out_t *endpoint);
diff --git a/tmk_core/protocol/chibios/usb_endpoints.c b/tmk_core/protocol/chibios/usb_endpoints.c
index 00536845b23..58872673365 100644
--- a/tmk_core/protocol/chibios/usb_endpoints.c
+++ b/tmk_core/protocol/chibios/usb_endpoints.c
@@ -80,6 +80,10 @@ usb_endpoint_in_t usb_endpoints_in[USB_ENDPOINT_IN_COUNT] = {
# endif
#endif
+#if defined(PLOVER_HID_ENABLE)
+ [USB_ENDPOINT_IN_PLOVER_HID] = QMK_USB_ENDPOINT_IN(USB_EP_MODE_TYPE_INTR, PLOVER_HID_EPSIZE, PLOVER_HID_IN_EPNUM, PLOVER_HID_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(PLOVER_HID_EPSIZE)),
+#endif
+
#if defined(MIDI_ENABLE)
# if defined(USB_ENDPOINTS_ARE_REORDERABLE)
[USB_ENDPOINT_IN_MIDI] = QMK_USB_ENDPOINT_IN_SHARED(USB_EP_MODE_TYPE_BULK, MIDI_STREAM_EPSIZE, MIDI_STREAM_IN_EPNUM, MIDI_STREAM_IN_CAPACITY, NULL, NULL),
@@ -107,6 +111,10 @@ usb_endpoint_in_lut_t usb_endpoint_interface_lut[TOTAL_INTERFACES] = {
[RAW_INTERFACE] = USB_ENDPOINT_IN_RAW,
#endif
+#if defined(PLOVER_HID_ENABLE)
+ [PLOVER_HID_INTERFACE] = USB_ENDPOINT_IN_PLOVER_HID,
+#endif
+
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
[MOUSE_INTERFACE] = USB_ENDPOINT_IN_MOUSE,
#endif
diff --git a/tmk_core/protocol/chibios/usb_endpoints.h b/tmk_core/protocol/chibios/usb_endpoints.h
index 9fad83726e9..4662db393f0 100644
--- a/tmk_core/protocol/chibios/usb_endpoints.h
+++ b/tmk_core/protocol/chibios/usb_endpoints.h
@@ -43,6 +43,10 @@
# define RAW_OUT_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
#endif
+#if !defined(PLOVER_HID_IN_CAPACITY)
+# define PLOVER_HID_IN_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
+#endif
+
#if !defined(MIDI_STREAM_IN_CAPACITY)
# define MIDI_STREAM_IN_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
#endif
@@ -90,6 +94,10 @@ typedef enum {
USB_ENDPOINT_IN_RAW,
#endif
+#if defined(PLOVER_HID_ENABLE)
+ USB_ENDPOINT_IN_PLOVER_HID,
+#endif
+
#if defined(MIDI_ENABLE)
USB_ENDPOINT_IN_MIDI,
#endif
@@ -127,6 +135,7 @@ typedef enum {
#if defined(RAW_ENABLE)
USB_ENDPOINT_OUT_RAW,
#endif
+
#if defined(MIDI_ENABLE)
USB_ENDPOINT_OUT_MIDI,
#endif
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index b8497684d67..5939e3273b9 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -489,6 +489,12 @@ void send_digitizer(report_digitizer_t *report) {
#endif
}
+void send_plover_hid(report_plover_hid_t *report) {
+#ifdef PLOVER_HID_ENABLE
+ send_report(USB_ENDPOINT_IN_PLOVER_HID, report, sizeof(report_plover_hid_t));
+#endif
+}
+
/* ---------------------------------------------------------
* Console functions
* ---------------------------------------------------------
@@ -578,8 +584,9 @@ __attribute__((weak)) void virtser_recv(uint8_t c) {
void virtser_task(void) {
uint8_t buffer[CDC_EPSIZE];
- while (receive_report(USB_ENDPOINT_OUT_CDC_DATA, buffer, sizeof(buffer))) {
- for (int i = 0; i < sizeof(buffer); i++) {
+ size_t received;
+ while ((received = usb_endpoint_out_receive_bytes(&usb_endpoints_out[USB_ENDPOINT_OUT_CDC_DATA], buffer, sizeof(buffer), TIME_IMMEDIATE)) > 0) {
+ for (size_t i = 0; i < received; i++) {
virtser_recv(buffer[i]);
}
}
diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c
index f4fa9064e03..8d326026074 100644
--- a/tmk_core/protocol/host.c
+++ b/tmk_core/protocol/host.c
@@ -342,6 +342,14 @@ void host_programmable_button_send(uint32_t data) {
__attribute__((weak)) void send_programmable_button(report_programmable_button_t *report) {}
+#ifdef PLOVER_HID_ENABLE
+void host_plover_hid_send(report_plover_hid_t *report) {
+ send_plover_hid(report);
+}
+#endif
+
+__attribute__((weak)) void send_plover_hid(report_plover_hid_t *report) {}
+
#ifdef RAW_ENABLE
void host_raw_hid_send(uint8_t *data, uint8_t length) {
host_driver_t *driver = host_get_active_driver();
diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h
index 7ff6d0df08d..c34a3f927c4 100644
--- a/tmk_core/protocol/host.h
+++ b/tmk_core/protocol/host.h
@@ -44,6 +44,7 @@ void host_mouse_send(report_mouse_t *report);
void host_system_send(uint16_t usage);
void host_consumer_send(uint16_t usage);
void host_programmable_button_send(uint32_t data);
+void host_plover_hid_send(report_plover_hid_t *report);
void host_raw_hid_send(uint8_t *data, uint8_t length);
uint16_t host_last_system_usage(void);
diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h
index c2835aaa99f..f65c367e020 100644
--- a/tmk_core/protocol/host_driver.h
+++ b/tmk_core/protocol/host_driver.h
@@ -37,3 +37,4 @@ typedef struct {
void send_joystick(report_joystick_t *report);
void send_digitizer(report_digitizer_t *report);
void send_programmable_button(report_programmable_button_t *report);
+void send_plover_hid(report_plover_hid_t *report);
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 3e442ba033a..827dd4d69a4 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -347,6 +347,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
ConfigSuccess &= Endpoint_ConfigureEndpoint((RAW_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, RAW_EPSIZE, 1);
#endif
+#ifdef PLOVER_HID_ENABLE
+ /* Setup plover HID endpoints */
+ ConfigSuccess &= Endpoint_ConfigureEndpoint((PLOVER_HID_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, PLOVER_HID_EPSIZE, 1);
+#endif
+
#ifdef CONSOLE_ENABLE
/* Setup console endpoint */
ConfigSuccess &= Endpoint_ConfigureEndpoint((CONSOLE_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, CONSOLE_EPSIZE, 1);
@@ -571,6 +576,12 @@ void send_digitizer(report_digitizer_t *report) {
#endif
}
+void send_plover_hid(report_plover_hid_t *report) {
+#ifdef PLOVER_HID_ENABLE
+ send_report(PLOVER_HID_IN_EPNUM, report, sizeof(report_plover_hid_t));
+#endif
+}
+
/*******************************************************************************
* sendchar
******************************************************************************/
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h
index ec220c6938d..805f8a91745 100644
--- a/tmk_core/protocol/report.h
+++ b/tmk_core/protocol/report.h
@@ -44,6 +44,11 @@ enum hid_report_ids {
#define IS_VALID_REPORT_ID(id) ((id) >= REPORT_ID_ALL && (id) <= REPORT_ID_COUNT)
+// Plover HID has its own dedicated interface rather than the shared endpoint, so its report ID
+// is fixed by the protocol at 0x50 ('P') and is intentionally NOT a member of enum
+// hid_report_ids above (which only enumerates shared-endpoint reports up to REPORT_ID_COUNT).
+#define REPORT_ID_PLOVER_HID 0x50
+
/* Mouse buttons */
#define MOUSE_BTN_MASK(n) (1 << (n))
enum mouse_buttons {
@@ -193,6 +198,11 @@ typedef struct {
uint32_t usage;
} PACKED report_programmable_button_t;
+typedef struct {
+ uint8_t report_id; // REPORT_ID_PLOVER_HID
+ uint8_t data[8];
+} PACKED report_plover_hid_t;
+
#ifdef MOUSE_EXTENDED_REPORT
# define MOUSE_REPORT_XY_MIN (INT16_MIN + 1)
# define MOUSE_REPORT_XY_MAX INT16_MAX
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index 38abb3781cd..f83f3c6b660 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -40,6 +40,7 @@
#include "report.h"
#include "usb_descriptor.h"
#include "usb_descriptor_common.h"
+#include "compiler_support.h"
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
@@ -370,10 +371,10 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
HID_RI_USAGE(8, 0x80), // System Control
HID_RI_COLLECTION(8, 0x01), // Application
HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
- HID_RI_USAGE_MINIMUM(8, 0x01), // Pointer
- HID_RI_USAGE_MAXIMUM(16, 0x00B7), // System Display LCD Autoscale
- HID_RI_LOGICAL_MINIMUM(8, 0x01),
- HID_RI_LOGICAL_MAXIMUM(16, 0x00B7),
+ HID_RI_USAGE_MINIMUM(16, SYSTEM_CONTROL_USAGE_MINIMUM),
+ HID_RI_USAGE_MAXIMUM(16, SYSTEM_CONTROL_USAGE_MAXIMUM),
+ HID_RI_LOGICAL_MINIMUM(16, SYSTEM_CONTROL_USAGE_MINIMUM),
+ HID_RI_LOGICAL_MAXIMUM(16, SYSTEM_CONTROL_USAGE_MAXIMUM),
HID_RI_REPORT_COUNT(8, 1),
HID_RI_REPORT_SIZE(8, 16),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
@@ -478,6 +479,28 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = {
};
#endif
+#ifdef PLOVER_HID_ENABLE
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM PloverReport[] = {
+ HID_RI_USAGE_PAGE(16, 0xFF50), //
+ HID_RI_USAGE(16, 0x4C56), // Vendor Defined (0xff P L V)
+ HID_RI_COLLECTION(8, 0x01), // Application
+ HID_RI_REPORT_ID(8, REPORT_ID_PLOVER_HID),
+ HID_RI_LOGICAL_MINIMUM(8, 0),
+ HID_RI_LOGICAL_MAXIMUM(8, 1),
+ HID_RI_REPORT_SIZE(8, 1),
+ HID_RI_REPORT_COUNT(8, 0x40),
+ HID_RI_USAGE_PAGE(8, 0x0A), // Usage Page: Ordinal
+ HID_RI_USAGE_MINIMUM(8, 0),
+ HID_RI_USAGE_MAXIMUM(8, 0x3F),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+};
+
+// The Plover HID report is sent with sizeof(report_plover_hid_t), but the endpoint and descriptor
+// are sized with PLOVER_HID_EPSIZE; they must match or reports get truncated/padded.
+STATIC_ASSERT(sizeof(report_plover_hid_t) == PLOVER_HID_EPSIZE, "report_plover_hid_t size must match PLOVER_HID_EPSIZE");
+#endif
+
#ifdef CONSOLE_ENABLE
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible)
@@ -643,6 +666,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
},
#endif
+#ifdef PLOVER_HID_ENABLE
+ /*
+ * Plover HID
+ */
+ .Plover_Interface = {
+ .Header = {
+ .Size = sizeof(USB_Descriptor_Interface_t),
+ .Type = DTYPE_Interface
+ },
+ .InterfaceNumber = PLOVER_HID_INTERFACE,
+ .AlternateSetting = 0x00,
+ .TotalEndpoints = 1,
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_NonBootSubclass,
+ .Protocol = HID_CSCP_NonBootProtocol,
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+ .Plover_HID = {
+ .Header = {
+ .Size = sizeof(USB_HID_Descriptor_HID_t),
+ .Type = HID_DTYPE_HID
+ },
+ .HIDSpec = VERSION_BCD(1, 1, 1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(PloverReport)
+ },
+ .Plover_INEndpoint = {
+ .Header = {
+ .Size = sizeof(USB_Descriptor_Endpoint_t),
+ .Type = DTYPE_Endpoint
+ },
+ .EndpointAddress = (ENDPOINT_DIR_IN | PLOVER_HID_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = PLOVER_HID_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+#endif
+
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
/*
* Mouse
@@ -1285,6 +1348,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
+#ifdef PLOVER_HID_ENABLE
+ case PLOVER_HID_INTERFACE:
+ Address = &ConfigurationDescriptor.Plover_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+
+ break;
+#endif
+
#ifdef CONSOLE_ENABLE
case CONSOLE_INTERFACE:
Address = &ConfigurationDescriptor.Console_HID;
@@ -1342,6 +1413,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#endif
+#ifdef PLOVER_HID_ENABLE
+ case PLOVER_HID_INTERFACE:
+ Address = &PloverReport;
+ Size = sizeof(PloverReport);
+
+ break;
+#endif
+
#ifdef CONSOLE_ENABLE
case CONSOLE_INTERFACE:
Address = &ConsoleReport;
diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h
index 366a380fdde..27058b7c123 100644
--- a/tmk_core/protocol/usb_descriptor.h
+++ b/tmk_core/protocol/usb_descriptor.h
@@ -47,7 +47,7 @@
#ifdef PROTOCOL_CHIBIOS
# include
-# if STM32_USB_USE_OTG1 == TRUE
+# if STM32_USB_USE_OTG1 == TRUE || STM32_USB_USE_OTG2 == TRUE
# define USB_ENDPOINTS_ARE_REORDERABLE
# endif
#endif
@@ -78,6 +78,13 @@ typedef struct {
USB_Descriptor_Endpoint_t Raw_OUTEndpoint;
#endif
+#ifdef PLOVER_HID_ENABLE
+ // Plover HID Interface
+ USB_Descriptor_Interface_t Plover_Interface;
+ USB_HID_Descriptor_HID_t Plover_HID;
+ USB_Descriptor_Endpoint_t Plover_INEndpoint;
+#endif
+
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
// Mouse HID Interface
USB_Descriptor_Interface_t Mouse_Interface;
@@ -164,6 +171,10 @@ enum usb_interfaces {
RAW_INTERFACE,
#endif
+#ifdef PLOVER_HID_ENABLE
+ PLOVER_HID_INTERFACE,
+#endif
+
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
MOUSE_INTERFACE,
#endif
@@ -227,6 +238,10 @@ enum usb_endpoints {
# endif
#endif
+#ifdef PLOVER_HID_ENABLE
+ PLOVER_HID_IN_EPNUM = NEXT_EPNUM,
+#endif
+
#ifdef SHARED_EP_ENABLE
SHARED_IN_EPNUM = NEXT_EPNUM,
#endif
@@ -287,6 +302,7 @@ enum usb_endpoints {
#define SHARED_EPSIZE 32
#define MOUSE_EPSIZE 16
#define RAW_EPSIZE 32
+#define PLOVER_HID_EPSIZE 9
#define CONSOLE_EPSIZE 32
#define MIDI_STREAM_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8
diff --git a/tmk_core/protocol/usb_descriptor_common.h b/tmk_core/protocol/usb_descriptor_common.h
index a1dba288ba3..75ca84328c4 100644
--- a/tmk_core/protocol/usb_descriptor_common.h
+++ b/tmk_core/protocol/usb_descriptor_common.h
@@ -16,12 +16,28 @@
#pragma once
+#include "compiler_support.h"
+
// Prefix string literal with L for descriptors
#define USBCONCAT(a, b) a##b
#define USBSTR(s) USBCONCAT(L, s)
#define HID_VALUE_16(v) ((uint8_t)(v & 0xFF)), ((uint8_t)(v >> 8))
+/////////////////////
+// System Control usage range
+//
+// Keep this below the Generic Desktop D-pad usages (0x90 and up). If the range
+// reaches them, hosts like Steam see the D-pad and treat the keyboard as a gamepad.
+
+#ifndef SYSTEM_CONTROL_USAGE_MINIMUM
+# define SYSTEM_CONTROL_USAGE_MINIMUM 0x0081 // System Power Down
+#endif
+#ifndef SYSTEM_CONTROL_USAGE_MAXIMUM
+# define SYSTEM_CONTROL_USAGE_MAXIMUM 0x008F // System Warm Restart
+#endif
+STATIC_ASSERT(SYSTEM_CONTROL_USAGE_MINIMUM <= SYSTEM_CONTROL_USAGE_MAXIMUM, "SYSTEM_CONTROL_USAGE_MINIMUM must not be greater than SYSTEM_CONTROL_USAGE_MAXIMUM");
+
/////////////////////
// RAW Usage page and ID configuration
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index e2e28a2b105..7e8bc65eedf 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -68,6 +68,10 @@ enum usb_interfaces {
RAW_INTERFACE,
#endif
+#ifdef PLOVER_HID_ENABLE
+ PLOVER_HID_INTERFACE,
+#endif
+
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
SHARED_INTERFACE,
#endif
@@ -87,6 +91,10 @@ STATIC_ASSERT(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough availabl
# error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two.
#endif
+#if defined(PLOVER_HID_ENABLE) && defined(RAW_ENABLE)
+# error Plover HID shares an endpoint with Raw HID. Please disable one of the two.
+#endif
+
static report_keyboard_t keyboard_report_sent;
static void send_report_fragment(uint8_t endpoint, void *data, size_t size) {
@@ -281,6 +289,14 @@ void send_programmable_button(report_programmable_button_t *report) {
#endif
}
+#define PLOVER_HID_EPSIZE 9
+
+void send_plover_hid(report_plover_hid_t *report) {
+#ifdef PLOVER_HID_ENABLE
+ send_report(4, report, sizeof(report_plover_hid_t));
+#endif
+}
+
/*------------------------------------------------------------------*
* Request from host *
*------------------------------------------------------------------*/
@@ -586,18 +602,18 @@ const PROGMEM uchar shared_hid_report[] = {
#ifdef EXTRAKEY_ENABLE
// Extrakeys report descriptor
- 0x05, 0x01, // Usage Page (Generic Desktop)
- 0x09, 0x80, // Usage (System Control)
- 0xA1, 0x01, // Collection (Application)
- 0x85, REPORT_ID_SYSTEM, // Report ID
- 0x19, 0x01, // Usage Minimum (Pointer)
- 0x2A, 0xB7, 0x00, // Usage Maximum (System Display LCD Autoscale)
- 0x15, 0x01, // Logical Minimum
- 0x26, 0xB7, 0x00, // Logical Maximum
- 0x95, 0x01, // Report Count (1)
- 0x75, 0x10, // Report Size (16)
- 0x81, 0x00, // Input (Data, Array, Absolute)
- 0xC0, // End Collection
+ 0x05, 0x01, // Usage Page (Generic Desktop)
+ 0x09, 0x80, // Usage (System Control)
+ 0xA1, 0x01, // Collection (Application)
+ 0x85, REPORT_ID_SYSTEM, // Report ID
+ 0x1A, HID_VALUE_16(SYSTEM_CONTROL_USAGE_MINIMUM), // Usage Minimum
+ 0x2A, HID_VALUE_16(SYSTEM_CONTROL_USAGE_MAXIMUM), // Usage Maximum
+ 0x16, HID_VALUE_16(SYSTEM_CONTROL_USAGE_MINIMUM), // Logical Minimum
+ 0x26, HID_VALUE_16(SYSTEM_CONTROL_USAGE_MAXIMUM), // Logical Maximum
+ 0x95, 0x01, // Report Count (1)
+ 0x75, 0x10, // Report Size (16)
+ 0x81, 0x00, // Input (Data, Array, Absolute)
+ 0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
@@ -771,6 +787,26 @@ const PROGMEM uchar raw_hid_report[] = {
};
#endif
+#ifdef PLOVER_HID_ENABLE
+// clang-format off
+const PROGMEM uchar plover_hid_report[] = {
+ 0x06, 0x50, 0xFF, // Usage Page (Vendor Defined)
+ 0x0A, 0x56, 0x4C, // Usage (Vendor Defined) (0xff P L V)
+ 0xA1, 0x01, // Collection (Application)
+ 0x85, REPORT_ID_PLOVER_HID, // Report ID
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x75, 0x01, // Report Size (1)
+ 0x95, 0x40, // Report Count (43)
+ 0x05, 0x0A, // Usage Page: Ordinal
+ 0x19, 0x00, // Usage Minimum
+ 0x29, 0x3F, // Usage Maximum (63)
+ 0x81, 0x02, // Output (Data, Variable, Absolute)
+ 0xC0 // End Collection
+};
+// clang-format on
+#endif
+
#if defined(CONSOLE_ENABLE)
const PROGMEM uchar console_hid_report[] = {
0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible)
@@ -963,6 +999,46 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
},
# endif
+# if defined(PLOVER_HID_ENABLE)
+ /*
+ * Plover HID
+ */
+ .ploverInterface = {
+ .header = {
+ .bLength = sizeof(usbInterfaceDescriptor_t),
+ .bDescriptorType = USBDESCR_INTERFACE
+ },
+ .bInterfaceNumber = PLOVER_HID_INTERFACE,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = 0x03,
+ .bInterfaceSubClass = 0x00,
+ .bInterfaceProtocol = 0x00,
+ .iInterface = 0x00
+ },
+ .ploverHID = {
+ .header = {
+ .bLength = sizeof(usbHIDDescriptor_t),
+ .bDescriptorType = USBDESCR_HID
+ },
+ .bcdHID = 0x0101,
+ .bCountryCode = 0x00,
+ .bNumDescriptors = 1,
+ .bDescriptorType = USBDESCR_HID_REPORT,
+ .wDescriptorLength = sizeof(plover_hid_report)
+ },
+ .ploverINEndpoint = {
+ .header = {
+ .bLength = sizeof(usbEndpointDescriptor_t),
+ .bDescriptorType = USBDESCR_ENDPOINT
+ },
+ .bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP4_NUMBER),
+ .bmAttributes = 0x03,
+ .wMaxPacketSize = PLOVER_HID_EPSIZE,
+ .bInterval = 0x01
+ },
+# endif
+
# ifdef SHARED_EP_ENABLE
/*
* Shared
@@ -1140,6 +1216,13 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
break;
#endif
+#if defined(PLOVER_HID_ENABLE)
+ case PLOVER_HID_INTERFACE:
+ usbMsgPtr = (usbMsgPtr_t)plover_hid_report;
+ len = sizeof(plover_hid_report);
+ break;
+#endif
+
#ifdef SHARED_EP_ENABLE
case SHARED_INTERFACE:
usbMsgPtr = (usbMsgPtr_t)shared_hid_report;
diff --git a/tmk_core/protocol/vusb/vusb.h b/tmk_core/protocol/vusb/vusb.h
index 4750e95bf25..16a6b397cc4 100644
--- a/tmk_core/protocol/vusb/vusb.h
+++ b/tmk_core/protocol/vusb/vusb.h
@@ -104,6 +104,12 @@ typedef struct usbConfigurationDescriptor {
usbEndpointDescriptor_t rawOUTEndpoint;
#endif
+#if defined(PLOVER_HID_ENABLE)
+ usbInterfaceDescriptor_t ploverInterface;
+ usbHIDDescriptor_t ploverHID;
+ usbEndpointDescriptor_t ploverINEndpoint;
+#endif
+
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
usbInterfaceDescriptor_t sharedInterface;
usbHIDDescriptor_t sharedHID;
diff --git a/util/ci/discord-results.py b/util/ci/discord-results.py
index 70f6af4b17e..1dc6d2051c3 100755
--- a/util/ci/discord-results.py
+++ b/util/ci/discord-results.py
@@ -3,7 +3,6 @@
import argparse
import os
import re
-import sys
from pathlib import Path
from discord_webhook import DiscordWebhook, DiscordEmbed