diff --git a/.github/labeler.yml b/.github/labeler.yml
index 07a6c451cff8..95eaa49252dd 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -40,3 +40,7 @@ translation:
- docs/ru-ru/**/*
CI:
- .github/**/*
+dd:
+ - data/constants/**/*
+ - data/mappings/**/*
+ - data/schemas/**/*
diff --git a/.github/workflows/api.yml b/.github/workflows/api.yml
index 38c1cfe50691..db78f1611224 100644
--- a/.github/workflows/api.yml
+++ b/.github/workflows/api.yml
@@ -25,7 +25,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
diff --git a/.github/workflows/auto_tag.yml b/.github/workflows/auto_tag.yml
index 0fc5e8850551..b4465277b0d7 100644
--- a/.github/workflows/auto_tag.yml
+++ b/.github/workflows/auto_tag.yml
@@ -27,7 +27,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
diff --git a/.github/workflows/ci_builds.yml b/.github/workflows/ci_builds.yml
index b3bb83fa8500..7fa07fe09d90 100644
--- a/.github/workflows/ci_builds.yml
+++ b/.github/workflows/ci_builds.yml
@@ -33,7 +33,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{ github.event.inputs.branch || github.ref }}
@@ -53,7 +53,7 @@ jobs:
[ ! -f .failed ] || exit 1
- name: 'Upload artifacts'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: always()
with:
name: artifacts-${{ github.event.inputs.branch || github.ref_name }}-${{ matrix.keymap }}
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index 27bdcc562b78..77b5bfe0734d 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -24,7 +24,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: recursive
diff --git a/.github/workflows/develop_update.yml b/.github/workflows/develop_update.yml
index 9c041c42ec8e..afcda1fe98bb 100644
--- a/.github/workflows/develop_update.yml
+++ b/.github/workflows/develop_update.yml
@@ -15,7 +15,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 39a8e396becd..fc0ed11c43ff 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -23,7 +23,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 1
@@ -37,7 +37,7 @@ jobs:
qmk --verbose generate-docs
- name: Deploy
- uses: JamesIves/github-pages-deploy-action@v4.4.3
+ uses: JamesIves/github-pages-deploy-action@v4.5.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_BRANCH: master
diff --git a/.github/workflows/feature_branch_update.yml b/.github/workflows/feature_branch_update.yml
index 097605516093..283a255342d8 100644
--- a/.github/workflows/feature_branch_update.yml
+++ b/.github/workflows/feature_branch_update.yml
@@ -21,7 +21,7 @@ jobs:
- riot
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
index 3652071ed6e9..81da72046c84 100644
--- a/.github/workflows/format.yml
+++ b/.github/workflows/format.yml
@@ -25,7 +25,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -35,7 +35,7 @@ jobs:
- name: Get changed files
id: file_changes
- uses: tj-actions/changed-files@v37
+ uses: tj-actions/changed-files@v42
- name: Run qmk formatters
shell: 'bash {0}'
diff --git a/.github/workflows/format_push.yml b/.github/workflows/format_push.yml
index 45c8b3daf617..61b4caf422d2 100644
--- a/.github/workflows/format_push.yml
+++ b/.github/workflows/format_push.yml
@@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index 95f58ff003f1..fa4b8981add9 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler.yml
@@ -12,7 +12,7 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- - uses: actions/labeler@main
+ - uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: '.github/labeler.yml'
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 1c0667abbacd..67823103f1bb 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -18,7 +18,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -27,7 +27,7 @@ jobs:
- name: Get changed files
id: file_changes
- uses: tj-actions/changed-files@v37
+ uses: tj-actions/changed-files@v42
- name: Print info
run: |
@@ -74,31 +74,10 @@ jobs:
fi
exit $exit_code
- - name: Verify at most one added keyboard
+ - name: Verify keyboard aliases
if: always()
shell: 'bash {0}'
run: |
git reset --hard
git clean -xfd
-
- # Get the keyboard list and count for the target branch
- git checkout -f ${{ github.base_ref }}
- git pull --ff-only
- QMK_KEYBOARDS_BASE=$(qmk list-keyboards)
- QMK_KEYBOARDS_BASE_COUNT=$(qmk list-keyboards | wc -l)
-
- # Get the keyboard list and count for the PR
- git checkout -f ${{ github.head_ref }}
- git merge --no-commit --squash ${{ github.base_ref }}
- QMK_KEYBOARDS_PR=$(qmk list-keyboards)
- QMK_KEYBOARDS_PR_COUNT=$(qmk list-keyboards | wc -l)
-
- echo "::group::Keyboards changes in this PR"
- diff -d -U 0 <(echo "$QMK_KEYBOARDS_BASE") <(echo "$QMK_KEYBOARDS_PR") | grep -vE '^(---|\+\+\+|@@)' | sed -e 's@^-@Removed: @g' -e 's@^+@ Added: @g'
- echo "::endgroup::"
-
- if [[ $QMK_KEYBOARDS_PR_COUNT -gt $(($QMK_KEYBOARDS_BASE_COUNT + 1)) ]]; then
- echo "More than one keyboard added in this PR -- see the PR Checklist."
- echo "::error::More than one keyboard added in this PR -- see the PR Checklist."
- exit 1
- fi
+ qmk ci-validate-aliases
diff --git a/.github/workflows/regen.yml b/.github/workflows/regen.yml
index a2b4ef2b934b..a31526084f9e 100644
--- a/.github/workflows/regen.yml
+++ b/.github/workflows/regen.yml
@@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Run qmk generators
run: |
diff --git a/.github/workflows/regen_push.yml b/.github/workflows/regen_push.yml
index 7394925a0de9..f1b781293767 100644
--- a/.github/workflows/regen_push.yml
+++ b/.github/workflows/regen_push.yml
@@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check
run : git config --global --add safe.directory '*'
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Run qmk generators
run: |
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index f011fb5460d2..ce9bd0f3161e 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -3,6 +3,7 @@ name: 'Close stale issues and PRs'
permissions:
issues: write
pull-requests: write
+ actions: write
on:
schedule:
@@ -13,7 +14,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v8
+ - uses: actions/stale@main
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml
index fb538d4f841c..eec8c8b5fc23 100644
--- a/.github/workflows/unit_test.yml
+++ b/.github/workflows/unit_test.yml
@@ -26,7 +26,7 @@ jobs:
container: ghcr.io/qmk/qmk_cli
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
diff --git a/.gitignore b/.gitignore
index 13ed2960352a..ca9f00a73308 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,11 @@
*.lst
*.map
*.o
+*.a
+*.so
+*.dylib
+*.dll
+*.la
*.stackdump
*.sym
@@ -95,6 +100,7 @@ secrets.tar
# Python things
__pycache__
.python-version
+.venv
# Prerequisites for updating ChibiOS
/util/fmpp*
@@ -107,5 +113,6 @@ compile_commands.json
.clangd/
.cache/
-# VIA(L) json files that don't belong in QMK repo
+# VIA(L) files that don't belong in QMK repo
via*.json
+/keyboards/**/keymaps/vial/*
diff --git a/Makefile b/Makefile
index c77eadf97d5d..ab30a17f58af 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,11 @@ $(info QMK Firmware $(QMK_VERSION))
endif
endif
+# Try to determine userspace from qmk config, if set.
+ifeq ($(QMK_USERSPACE),)
+ QMK_USERSPACE = $(shell qmk config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
+endif
+
# Determine which qmk cli to use
QMK_BIN := qmk
@@ -191,9 +196,20 @@ define PARSE_KEYBOARD
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.)))
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.)))
+ ifneq ($(QMK_USERSPACE),)
+ KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_1)/keymaps/*/.)))
+ KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_2)/keymaps/*/.)))
+ KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/keymaps/*/.)))
+ KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.)))
+ KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.)))
+ endif
+
KEYBOARD_LAYOUTS := $(shell $(QMK_BIN) list-layouts --keyboard $1)
LAYOUT_KEYMAPS :=
$$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/layouts/*/$$(LAYOUT)/*/.)))))
+ ifneq ($(QMK_USERSPACE),)
+ $$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/layouts/$$(LAYOUT)/*/.)))))
+ endif
KEYMAPS := $$(sort $$(KEYMAPS) $$(LAYOUT_KEYMAPS))
@@ -300,17 +316,18 @@ endef
define BUILD_TEST
TEST_PATH := $1
TEST_NAME := $$(notdir $$(TEST_PATH))
+ TEST_FULL_NAME := $$(subst /,_,$$(patsubst $$(ROOT_DIR)tests/%,%,$$(TEST_PATH)))
MAKE_TARGET := $2
COMMAND := $1
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET)
- MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
+ MAKE_VARS := TEST=$$(TEST_NAME) TEST_OUTPUT=$$(TEST_FULL_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
MAKE_MSG := $$(MSG_MAKE_TEST)
$$(eval $$(call BUILD))
ifneq ($$(MAKE_TARGET),clean)
- TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf
- TESTS += $$(TEST_NAME)
+ TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_FULL_NAME).elf
+ TESTS += $$(TEST_FULL_NAME)
TEST_MSG := $$(MSG_TEST)
- $$(TEST_NAME)_COMMAND := \
+ $$(TEST_FULL_NAME)_COMMAND := \
printf "$$(TEST_MSG)\n"; \
$$(TEST_EXECUTABLE); \
if [ $$$$? -gt 0 ]; \
@@ -322,15 +339,22 @@ endef
define PARSE_TEST
TESTS :=
- TEST_NAME := $$(firstword $$(subst :, ,$$(RULE)))
- TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE)))
+ # list of possible targets, colon-delimited, to reassign to MAKE_TARGET and remove
+ TARGETS := :clean:
+ ifneq (,$$(findstring :$$(lastword $$(subst :, ,$$(RULE))):, $$(TARGETS)))
+ MAKE_TARGET := $$(lastword $$(subst :, ,$$(RULE)))
+ TEST_SUBPATH := $$(subst $$(eval) ,/,$$(wordlist 2, $$(words $$(subst :, ,$$(RULE))), _ $$(subst :, ,$$(RULE))))
+ else
+ MAKE_TARGET :=
+ TEST_SUBPATH := $$(subst :,/,$$(RULE))
+ endif
include $(BUILDDEFS_PATH)/testlist.mk
- ifeq ($$(TEST_NAME),all)
+ ifeq ($$(RULE),all)
MATCHED_TESTS := $$(TEST_LIST)
else
- MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),))
+ MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring /$$(TEST_SUBPATH)/, $$(patsubst %,%/,$$(TEST))), $$(TEST),))
endif
- $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
+ $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(MAKE_TARGET))))
endef
@@ -423,8 +447,18 @@ clean:
rm -rf $(BUILD_DIR)
echo 'done.'
-.PHONY: distclean
-distclean: clean
+.PHONY: distclean distclean_qmk
+distclean: distclean_qmk
+distclean_qmk: clean
echo -n 'Deleting *.bin, *.hex, and *.uf2 ... '
rm -f *.bin *.hex *.uf2
echo 'done.'
+
+ifneq ($(QMK_USERSPACE),)
+.PHONY: distclean_userspace
+distclean: distclean_userspace
+distclean_userspace: clean
+ echo -n 'Deleting userspace *.bin, *.hex, and *.uf2 ... '
+ rm -f $(QMK_USERSPACE)/*.bin $(QMK_USERSPACE)/*.hex $(QMK_USERSPACE)/*.uf2
+ echo 'done.'
+endif
diff --git a/builddefs/build_full_test.mk b/builddefs/build_full_test.mk
index 964ba773d48c..63f9fea915db 100644
--- a/builddefs/build_full_test.mk
+++ b/builddefs/build_full_test.mk
@@ -13,11 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-$(TEST)_INC := \
+$(TEST_OUTPUT)_INC := \
tests/test_common/common_config.h
-$(TEST)_SRC := \
- $(TMK_COMMON_SRC) \
+$(TEST_OUTPUT)_SRC := \
$(QUANTUM_SRC) \
$(SRC) \
$(QUANTUM_PATH)/keymap_introspection.c \
@@ -31,8 +30,8 @@ $(TEST)_SRC := \
tests/test_common/test_logger.cpp \
$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
-$(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
+$(TEST_OUTPUT)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
-$(TEST)_CONFIG := $(TEST_PATH)/config.h
+$(TEST_OUTPUT)_CONFIG := $(TEST_PATH)/config.h
VPATH += $(TOP_DIR)/tests/test_common
diff --git a/builddefs/build_json.mk b/builddefs/build_json.mk
index 0c034eb2aea0..e9d1420f3639 100644
--- a/builddefs/build_json.mk
+++ b/builddefs/build_json.mk
@@ -1,17 +1,36 @@
# Look for a json keymap file
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","")
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
+ KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_5)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","")
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
+ KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_4)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","")
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
+ KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_3)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","")
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
+ KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_2)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
+ KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_1)
+endif
+
+ifneq ($(QMK_USERSPACE),)
+ ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.json)","")
+ KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.json
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.json)","")
+ KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.json
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.json)","")
+ KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.json
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.json)","")
+ KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.json
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.json)","")
+ KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.json
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)
+ endif
endif
diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk
index 0425d3fc9d76..f17171fe209b 100644
--- a/builddefs/build_keyboard.mk
+++ b/builddefs/build_keyboard.mk
@@ -27,7 +27,6 @@ QMK_BIN ?= qmk
# Set the filename for the final firmware binary
KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD))
TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP)
-KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
ifeq ($(strip $(DUMP_CI_METADATA)),yes)
$(info CI Metadata: KEYBOARD=$(KEYBOARD))
@@ -44,7 +43,7 @@ endif
# Object files and generated keymap directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
-KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
+INTERMEDIATE_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
ifdef SKIP_VERSION
OPT_DEFS += -DSKIP_VERSION
@@ -60,7 +59,7 @@ VERSION_H_FLAGS += --skip-git
endif
# Generate the board's version.h file.
-$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(KEYMAP_OUTPUT)/src/version.h)
+$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(INTERMEDIATE_OUTPUT)/src/version.h)
# Determine which subfolders exist.
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD)
@@ -121,7 +120,7 @@ MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
# Pull in rules from info.json
-INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_rules.mk)
+INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_rules.mk)
include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c
@@ -130,59 +129,90 @@ include $(BUILDDEFS_PATH)/build_json.mk
# Pull in keymap level rules.mk
ifeq ("$(wildcard $(KEYMAP_PATH))", "")
# Look through the possible keymap folders until we find a matching keymap.c
- ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
- -include $(MAIN_KEYMAP_PATH_1)/rules.mk
- KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
- else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
- -include $(MAIN_KEYMAP_PATH_2)/rules.mk
- KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
- else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
- -include $(MAIN_KEYMAP_PATH_3)/rules.mk
- KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
- else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
- -include $(MAIN_KEYMAP_PATH_4)/rules.mk
- KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
- else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
- -include $(MAIN_KEYMAP_PATH_5)/rules.mk
- KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
- KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
- else ifneq ($(LAYOUTS),)
- # If we haven't found a keymap yet fall back to community layouts
- include $(BUILDDEFS_PATH)/build_layout.mk
- else
- $(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
- # this state should never be reached
+ ifneq ($(QMK_USERSPACE),)
+ ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c)","")
+ -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/rules.mk
+ KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c)","")
+ -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/rules.mk
+ KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c)","")
+ -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/rules.mk
+ KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c)","")
+ -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/rules.mk
+ KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)
+ else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c)","")
+ -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/rules.mk
+ KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c
+ KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)
+ endif
+ endif
+ ifeq ($(KEYMAP_PATH),)
+ ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
+ -include $(MAIN_KEYMAP_PATH_1)/rules.mk
+ KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
+ KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
+ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
+ -include $(MAIN_KEYMAP_PATH_2)/rules.mk
+ KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
+ KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
+ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
+ -include $(MAIN_KEYMAP_PATH_3)/rules.mk
+ KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
+ KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
+ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
+ -include $(MAIN_KEYMAP_PATH_4)/rules.mk
+ KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
+ KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
+ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
+ -include $(MAIN_KEYMAP_PATH_5)/rules.mk
+ KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
+ KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
+ else ifneq ($(LAYOUTS),)
+ # If we haven't found a keymap yet fall back to community layouts
+ include $(BUILDDEFS_PATH)/build_layout.mk
+ else ifeq ("$(wildcard $(KEYMAP_JSON_PATH))", "") # Not finding keymap.c is fine if we found a keymap.json
+ $(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
+ # this state should never be reached
+ endif
endif
endif
# Have we found a keymap.json?
ifneq ("$(wildcard $(KEYMAP_JSON))", "")
- KEYMAP_C := $(KEYMAP_OUTPUT)/src/keymap.c
- KEYMAP_H := $(KEYMAP_OUTPUT)/src/config.h
+ ifneq ("$(wildcard $(KEYMAP_C))", "")
+ $(call WARNING_MESSAGE,Keymap is specified as both keymap.json and keymap.c -- keymap.json file wins.)
+ endif
+
+ KEYMAP_PATH := $(KEYMAP_JSON_PATH)
+
+ KEYMAP_C := $(INTERMEDIATE_OUTPUT)/src/keymap.c
+ KEYMAP_H := $(INTERMEDIATE_OUTPUT)/src/config.h
# Load the keymap-level rules.mk if exists
-include $(KEYMAP_PATH)/rules.mk
# Load any rules.mk content from keymap.json
- INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --output $(KEYMAP_OUTPUT)/src/rules.mk $(KEYMAP_JSON))
+ INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --output $(INTERMEDIATE_OUTPUT)/src/rules.mk $(KEYMAP_JSON))
include $(INFO_RULES_MK)
# Add rules to generate the keymap files - indentation here is important
-$(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
+$(INTERMEDIATE_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON))
@$(BUILD_CMD)
-$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON)
+$(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON))
@$(BUILD_CMD)
-generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c
+generated-files: $(INTERMEDIATE_OUTPUT)/src/config.h $(INTERMEDIATE_OUTPUT)/src/keymap.c
endif
@@ -323,34 +353,34 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json
endif
-CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h
-KEYBOARD_SRC += $(KEYBOARD_OUTPUT)/src/default_keyboard.c
+CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
+KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
-$(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
+$(INTERMEDIATE_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
- $(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h)
+ $(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_config.h)
@$(BUILD_CMD)
-$(KEYBOARD_OUTPUT)/src/default_keyboard.c: $(INFO_JSON_FILES)
+$(INTERMEDIATE_OUTPUT)/src/default_keyboard.c: $(INFO_JSON_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
- $(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.c)
+ $(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c)
@$(BUILD_CMD)
-$(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES)
+$(INTERMEDIATE_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
- $(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h)
+ $(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h)
@$(BUILD_CMD)
-generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.c $(KEYBOARD_OUTPUT)/src/default_keyboard.h
+generated-files: $(INTERMEDIATE_OUTPUT)/src/info_config.h $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h
-generated-files: $(KEYMAP_OUTPUT)/src/info_deps.d
+generated-files: $(INTERMEDIATE_OUTPUT)/src/info_deps.d
-$(KEYMAP_OUTPUT)/src/info_deps.d:
+$(INTERMEDIATE_OUTPUT)/src/info_deps.d:
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
- $(eval CMD=$(QMK_BIN) generate-make-dependencies -kb $(KEYBOARD) -km $(KEYMAP) -o $(KEYMAP_OUTPUT)/src/info_deps.d)
+ $(eval CMD=$(QMK_BIN) generate-make-dependencies -kb $(KEYBOARD) -km $(KEYMAP) -o $(INTERMEDIATE_OUTPUT)/src/info_deps.d)
@$(BUILD_CMD)
--include $(KEYMAP_OUTPUT)/src/info_deps.d
+-include $(INTERMEDIATE_OUTPUT)/src/info_deps.d
.INTERMEDIATE : generated-files
@@ -360,6 +390,16 @@ ifeq ("$(USER_NAME)","")
endif
USER_PATH := users/$(USER_NAME)
+# If we have userspace, then add it to the lookup VPATH
+ifneq ($(wildcard $(QMK_USERSPACE)),)
+ VPATH += $(QMK_USERSPACE)
+endif
+
+# If the equivalent users directory exists in userspace, use that in preference to anything currently in the main repo
+ifneq ($(wildcard $(QMK_USERSPACE)/$(USER_PATH)),)
+ USER_PATH := $(QMK_USERSPACE)/$(USER_PATH)
+endif
+
# Pull in user level rules.mk
-include $(USER_PATH)/rules.mk
ifneq ("$(wildcard $(USER_PATH)/config.h)","")
@@ -400,6 +440,10 @@ ifneq ("$(KEYMAP_H)","")
CONFIG_H += $(KEYMAP_H)
endif
+ifeq ($(KEYMAP_C),)
+ $(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
+endif
+
OPT_DEFS += -DKEYMAP_C=\"$(KEYMAP_C)\"
# If a keymap or userspace places their keymap array in another file instead, allow for it to be included
@@ -423,8 +467,7 @@ VPATH += $(KEYMAP_PATH)
VPATH += $(USER_PATH)
VPATH += $(KEYBOARD_PATHS)
VPATH += $(COMMON_VPATH)
-VPATH += $(KEYBOARD_OUTPUT)/src
-VPATH += $(KEYMAP_OUTPUT)/src
+VPATH += $(INTERMEDIATE_OUTPUT)/src
include $(BUILDDEFS_PATH)/common_features.mk
include $(BUILDDEFS_PATH)/generic_features.mk
@@ -433,19 +476,17 @@ include $(PLATFORM_PATH)/common.mk
SRC += $(patsubst %.c,%.clib,$(LIB_SRC))
SRC += $(patsubst %.c,%.clib,$(QUANTUM_LIB_SRC))
-SRC += $(TMK_COMMON_SRC)
-OPT_DEFS += $(TMK_COMMON_DEFS)
-EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/bootloader.mk
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk
ifneq ($(strip $(PROTOCOL)),)
- include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk
+PROTOCOL_KEY = $(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]'))
else
- include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
+PROTOCOL_KEY = $(PLATFORM_KEY)
endif
+include $(TMK_PATH)/protocol/$(PROTOCOL_KEY)/$(PROTOCOL_KEY).mk
# Setup definitions based on the selected MCU
$(eval $(call add_qmk_prefix_defs,MCU_ORIG,MCU))
@@ -454,6 +495,7 @@ $(eval $(call add_qmk_prefix_defs,MCU_PORT_NAME,MCU_PORT_NAME))
$(eval $(call add_qmk_prefix_defs,MCU_FAMILY,MCU_FAMILY))
$(eval $(call add_qmk_prefix_defs,MCU_SERIES,MCU_SERIES))
$(eval $(call add_qmk_prefix_defs,BOARD,BOARD))
+$(eval $(call add_qmk_prefix_defs,OPT,OPT))
# Control whether intermediate file listings are generated
# e.g.:
@@ -471,17 +513,14 @@ PROJECT_CONFIG := $(CONFIG_H)
CONFIG_H += $(POST_CONFIG_H)
ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H)
-OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT)
-$(KEYMAP_OUTPUT)_SRC := $(SRC)
-$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \
--DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(KEYBOARD_OUTPUT)/src/default_keyboard.h\" \
--DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\"
-$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS)
-$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H)
-$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC)
-$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS)
-$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC)
-$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
+OUTPUTS := $(INTERMEDIATE_OUTPUT)
+$(INTERMEDIATE_OUTPUT)_SRC := $(SRC) $(PLATFORM_SRC)
+$(INTERMEDIATE_OUTPUT)_DEFS := $(OPT_DEFS) \
+ -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(INTERMEDIATE_OUTPUT)/src/default_keyboard.h\" \
+ -DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" \
+ $(PROJECT_DEFS)
+$(INTERMEDIATE_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(PROJECT_INC)
+$(INTERMEDIATE_OUTPUT)_CONFIG := $(CONFIG_H) $(PROJECT_CONFIG)
# Default target.
all: build check-size
@@ -502,10 +541,10 @@ check-size: top-symbols
top-symbols: build
echo "###########################################"
echo "# Highest flash usage:"
- $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep -i ' [t] ' | head -n$(NUM_TOP_SYMBOLS) | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
+ $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep ' [RrTt] ' | head -n$(NUM_TOP_SYMBOLS) | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
echo "###########################################"
echo "# Highest RAM usage:"
- $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep -i ' [dbv] ' | head -n$(NUM_TOP_SYMBOLS) | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
+ $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep ' [BbCDdGgSs] ' | head -n$(NUM_TOP_SYMBOLS) | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
echo "###########################################"
endif
diff --git a/builddefs/build_layout.mk b/builddefs/build_layout.mk
index 6166bd847c59..9ff99cc2218e 100644
--- a/builddefs/build_layout.mk
+++ b/builddefs/build_layout.mk
@@ -1,6 +1,10 @@
LAYOUTS_PATH := layouts
LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/))))
+ifneq ($(QMK_USERSPACE),)
+ LAYOUTS_REPOS += $(patsubst %/,%,$(QMK_USERSPACE)/$(LAYOUTS_PATH))
+endif
+
define SEARCH_LAYOUTS_REPO
LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP)
LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json
diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk
index 9eead77beabd..2cc1134da5b3 100644
--- a/builddefs/build_test.mk
+++ b/builddefs/build_test.mk
@@ -9,13 +9,13 @@ OPT = g
include paths.mk
include $(BUILDDEFS_PATH)/message.mk
-TARGET=test/$(TEST)
+TARGET=test/$(TEST_OUTPUT)
GTEST_OUTPUT = $(BUILD_DIR)/gtest
TEST_OBJ = $(BUILD_DIR)/test_obj
-OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
+OUTPUTS := $(TEST_OBJ)/$(TEST_OUTPUT) $(GTEST_OUTPUT)
GTEST_INC := \
$(LIB_PATH)/googletest/googletest/include \
@@ -71,18 +71,18 @@ ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include $(BUILDDEFS_PATH)/build_full_test.mk
endif
-$(TEST)_SRC += \
+$(TEST_OUTPUT)_SRC += \
tests/test_common/main.cpp \
$(QUANTUM_PATH)/logging/print.c
ifneq ($(strip $(INTROSPECTION_KEYMAP_C)),)
-$(TEST)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
+$(TEST_OUTPUT)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
endif
-$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
-$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
-$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
-$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG)
+$(TEST_OBJ)/$(TEST_OUTPUT)_SRC := $($(TEST_OUTPUT)_SRC)
+$(TEST_OBJ)/$(TEST_OUTPUT)_INC := $($(TEST_OUTPUT)_INC) $(VPATH) $(GTEST_INC)
+$(TEST_OBJ)/$(TEST_OUTPUT)_DEFS := $($(TEST_OUTPUT)_DEFS)
+$(TEST_OBJ)/$(TEST_OUTPUT)_CONFIG := $($(TEST_OUTPUT)_CONFIG)
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
include $(BUILDDEFS_PATH)/common_rules.mk
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index e904d6beb975..60f1cbd837fa 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -75,10 +75,7 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
endif
ifeq ($(strip $(SEQUENCER_ENABLE)), yes)
- OPT_DEFS += -DSEQUENCER_ENABLE
MUSIC_ENABLE = yes
- SRC += $(QUANTUM_DIR)/sequencer/sequencer.c
- SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c
endif
ifeq ($(strip $(MIDI_ENABLE)), yes)
@@ -94,11 +91,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif
-MUSIC_ENABLE ?= no
-ifeq ($(MUSIC_ENABLE), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
-endif
-
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
STENO_PROTOCOL ?= all
ifeq ($(strip $(STENO_ENABLE)), yes)
@@ -124,17 +116,11 @@ ifeq ($(strip $(STENO_ENABLE)), yes)
endif
endif
-ifeq ($(strip $(VIRTSER_ENABLE)), yes)
- OPT_DEFS += -DVIRTSER_ENABLE
-endif
-
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
- OPT_DEFS += -DMOUSEKEY_ENABLE
MOUSE_ENABLE := yes
- SRC += $(QUANTUM_DIR)/mousekey.c
endif
-VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
+VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick azoteq_iqs5xx cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
@@ -151,30 +137,26 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
endif
OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER))
ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800)
- OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
- QUANTUM_LIB_SRC += spi_master.c
+ SPI_DRIVER_REQUIRED = yes
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick)
- OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE
- LIB_SRC += analog.c
+ ANALOG_DRIVER_REQUIRED = yes
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), azoteq_iqs5xx)
+ I2C_DRIVER_REQUIRED = yes
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c)
- OPT_DEFS += -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ I2C_DRIVER_REQUIRED = yes
SRC += drivers/sensors/cirque_pinnacle.c
SRC += drivers/sensors/cirque_pinnacle_gestures.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_gestures.c
- QUANTUM_LIB_SRC += i2c_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_spi)
- OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ SPI_DRIVER_REQUIRED = yes
SRC += drivers/sensors/cirque_pinnacle.c
SRC += drivers/sensors/cirque_pinnacle_gestures.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_gestures.c
- QUANTUM_LIB_SRC += spi_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball)
- OPT_DEFS += -DSTM32_SPI -DHAL_USE_I2C=TRUE
- QUANTUM_LIB_SRC += i2c_master.c
+ I2C_DRIVER_REQUIRED = yes
else ifneq ($(filter $(strip $(POINTING_DEVICE_DRIVER)),pmw3360 pmw3389),)
- OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ SPI_DRIVER_REQUIRED = yes
SRC += drivers/sensors/pmw33xx_common.c
- QUANTUM_LIB_SRC += spi_master.c
endif
endif
endif
@@ -204,12 +186,12 @@ else
else ifeq ($(strip $(EEPROM_DRIVER)), i2c)
# External I2C EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C
- QUANTUM_LIB_SRC += i2c_master.c
+ I2C_DRIVER_REQUIRED = yes
SRC += eeprom_driver.c eeprom_i2c.c
else ifeq ($(strip $(EEPROM_DRIVER)), spi)
# External SPI EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI
- QUANTUM_LIB_SRC += spi_master.c
+ SPI_DRIVER_REQUIRED = yes
SRC += eeprom_driver.c eeprom_spi.c
else ifeq ($(strip $(EEPROM_DRIVER)), legacy_stm32_flash)
# STM32 Emulated EEPROM, backed by MCU flash (soon to be deprecated)
@@ -308,23 +290,19 @@ ifneq ($(strip $(FLASH_DRIVER)), none)
else
OPT_DEFS += -DFLASH_ENABLE
ifeq ($(strip $(FLASH_DRIVER)),spi)
+ SPI_DRIVER_REQUIRED = yes
OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c
- QUANTUM_LIB_SRC += spi_master.c
endif
endif
endif
RGBLIGHT_ENABLE ?= no
-VALID_RGBLIGHT_TYPES := WS2812 APA102 custom
-
-ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
- RGBLIGHT_DRIVER ?= custom
-endif
+VALID_RGBLIGHT_TYPES := ws2812 apa102 custom
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
- RGBLIGHT_DRIVER ?= WS2812
+ RGBLIGHT_DRIVER ?= ws2812
ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
@@ -332,197 +310,236 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
COMMON_VPATH += $(QUANTUM_DIR)/rgblight
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h
OPT_DEFS += -DRGBLIGHT_ENABLE
+ OPT_DEFS += -DRGBLIGHT_$(strip $(shell echo $(RGBLIGHT_DRIVER) | tr '[:lower:]' '[:upper:]'))
SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgblight/rgblight.c
CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes
endif
- ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812)
+ ifeq ($(strip $(RGBLIGHT_DRIVER)), ws2812)
WS2812_DRIVER_REQUIRED := yes
endif
- ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102)
+ ifeq ($(strip $(RGBLIGHT_DRIVER)), apa102)
APA102_DRIVER_REQUIRED := yes
endif
- ifeq ($(strip $(RGBLIGHT_DRIVER)), custom)
- OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
+ ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
+ OPT_DEFS += -DVELOCIKEY_ENABLE
endif
endif
+# Deprecated driver names - do not use
+ifeq ($(strip $(LED_MATRIX_DRIVER)), aw20216)
+LED_MATRIX_DRIVER := aw20216s
+endif
+ifeq ($(strip $(LED_MATRIX_DRIVER)), ckled2001)
+LED_MATRIX_DRIVER := snled27351
+endif
+
LED_MATRIX_ENABLE ?= no
-VALID_LED_MATRIX_TYPES := IS31FL3731 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 custom
-# TODO: IS31FL3733 IS31FL3737 IS31FL3741
+VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 custom
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid LED_MATRIX_DRIVER,LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type)
endif
OPT_DEFS += -DLED_MATRIX_ENABLE
-ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
- # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
- OPT_DEFS += -DLIB8_ATTINY
-endif
+ OPT_DEFS += -DLED_MATRIX_$(strip $(shell echo $(LED_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
+
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners
+ POST_CONFIG_H += $(QUANTUM_DIR)/led_matrix/post_config.h
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
- SRC += $(LIB_PATH)/lib8tion/lib8tion.c
+ LIB8TION_ENABLE := yes
CIE1931_CURVE := yes
- ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
- OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3218)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3218-simple.c
+ endif
+
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3731)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731-simple.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3742A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3733)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3733-simple.c
+ endif
+
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3736)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3736-simple.c
+ endif
+
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3737)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3737-simple.c
+ endif
+
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3741)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3741-simple.c
+ endif
+
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3743A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3743a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3745)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3745)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3746A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3746a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(LED_MATRIX_DRIVER)), CKLED2001)
- OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(LED_MATRIX_DRIVER)), snled27351)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led
- SRC += ckled2001-simple.c
- QUANTUM_LIB_SRC += i2c_master.c
+ SRC += snled27351-simple.c
endif
endif
+# Deprecated driver names - do not use
+ifeq ($(strip $(RGB_MATRIX_DRIVER)), aw20216)
+RGB_MATRIX_DRIVER := aw20216s
+endif
+ifeq ($(strip $(RGB_MATRIX_DRIVER)), ckled2001)
+RGB_MATRIX_DRIVER := snled27351
+endif
+
RGB_MATRIX_ENABLE ?= no
-VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3736 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 WS2812 custom
+VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 ws2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
endif
OPT_DEFS += -DRGB_MATRIX_ENABLE
-ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
- # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
- OPT_DEFS += -DLIB8_ATTINY
-endif
+ OPT_DEFS += -DRGB_MATRIX_$(strip $(shell echo $(RGB_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
+
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners
+ POST_CONFIG_H += $(QUANTUM_DIR)/rgb_matrix/post_config.h
SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
- SRC += $(LIB_PATH)/lib8tion/lib8tion.c
+ LIB8TION_ENABLE := yes
CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216)
- OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), aw20216s)
+ SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led
- SRC += aw20216.c
- QUANTUM_LIB_SRC += spi_master.c
+ SRC += aw20216s.c
+ endif
+
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3218)
+ I2C_DRIVER_REQUIRED = yes
+ COMMON_VPATH += $(DRIVER_PATH)/led/issi
+ SRC += is31fl3218.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
- OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3731)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733)
- OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3733)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3733.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3736)
- OPT_DEFS += -DIS31FL3736 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3736)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3736.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737)
- OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3737)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3737.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741)
- OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3741)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3741.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3742A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3742a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3743A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3743a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3745)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3745)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3746A)
- OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3746a)
+ OPT_DEFS += -DIS31FLCOMMON
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
- QUANTUM_LIB_SRC += i2c_master.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001)
- OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), snled27351)
+ I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led
- SRC += ckled2001.c
- QUANTUM_LIB_SRC += i2c_master.c
+ SRC += snled27351.c
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812)
- OPT_DEFS += -DWS2812
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
WS2812_DRIVER_REQUIRED := yes
endif
- ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102)
- OPT_DEFS += -DAPA102
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), apa102)
APA102_DRIVER_REQUIRED := yes
endif
@@ -565,51 +582,23 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
endif
COMMON_VPATH += $(QUANTUM_DIR)/backlight
+ COMMON_VPATH += $(DRIVER_PATH)/backlight
SRC += $(QUANTUM_DIR)/backlight/backlight.c
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
OPT_DEFS += -DBACKLIGHT_ENABLE
+ OPT_DEFS += -DBACKLIGHT_$(strip $(shell echo $(BACKLIGHT_DRIVER) | tr '[:lower:]' '[:upper:]'))
- ifeq ($(strip $(BACKLIGHT_DRIVER)), custom)
- OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
- else
+ ifneq ($(strip $(BACKLIGHT_DRIVER)), custom)
SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c
- ifeq ($(strip $(BACKLIGHT_DRIVER)), pwm)
- SRC += $(QUANTUM_DIR)/backlight/backlight_$(PLATFORM_KEY).c
+
+ ifeq ($(strip $(BACKLIGHT_DRIVER)), software)
+ SRC += $(DRIVER_PATH)/backlight/backlight_software.c
else
- SRC += $(QUANTUM_DIR)/backlight/backlight_$(strip $(BACKLIGHT_DRIVER)).c
+ SRC += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/backlight_$(strip $(BACKLIGHT_DRIVER)).c
endif
endif
endif
-VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
-
-WS2812_DRIVER ?= bitbang
-ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
- ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),)
- $(call CATASTROPHIC_ERROR,Invalid WS2812_DRIVER,WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver)
- endif
-
- OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))
-
- SRC += ws2812_$(strip $(WS2812_DRIVER)).c
-
- ifeq ($(strip $(PLATFORM)), CHIBIOS)
- ifeq ($(strip $(WS2812_DRIVER)), pwm)
- OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
- endif
- endif
-
- # add extra deps
- ifeq ($(strip $(WS2812_DRIVER)), i2c)
- QUANTUM_LIB_SRC += i2c_master.c
- endif
-endif
-
-ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
- COMMON_VPATH += $(DRIVER_PATH)/led
- SRC += apa102.c
-endif
-
ifeq ($(strip $(CIE1931_CURVE)), yes)
OPT_DEFS += -DUSE_CIE1931_CURVE
LED_TABLES := yes
@@ -624,8 +613,6 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
RAW_ENABLE := yes
BOOTMAGIC_ENABLE := yes
TRI_LAYER_ENABLE := yes
- SRC += $(QUANTUM_DIR)/via.c
- OPT_DEFS += -DVIA_ENABLE
endif
VALID_MAGIC_TYPES := yes
@@ -710,29 +697,36 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
COMMON_VPATH += $(QUANTUM_PATH)/split_common
endif
-ifeq ($(strip $(CRC_ENABLE)), yes)
- OPT_DEFS += -DCRC_ENABLE
- SRC += crc.c
-endif
-
ifeq ($(strip $(FNV_ENABLE)), yes)
OPT_DEFS += -DFNV_ENABLE
VPATH += $(LIB_PATH)/fnv
SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
endif
+ifeq ($(strip $(LIB8TION_ENABLE)), yes)
+ ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
+ # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
+ OPT_DEFS += -DLIB8_ATTINY
+ endif
+ SRC += $(LIB_PATH)/lib8tion/lib8tion.c
+endif
+
+VALID_HAPTIC_DRIVER_TYPES := drv2605l solenoid
ifeq ($(strip $(HAPTIC_ENABLE)),yes)
- COMMON_VPATH += $(DRIVER_PATH)/haptic
+ ifeq ($(filter $(HAPTIC_DRIVER),$(VALID_HAPTIC_DRIVER_TYPES)),)
+ $(call CATASTROPHIC_ERROR,Invalid HAPTIC_DRIVER,HAPTIC_DRIVER="$(HAPTIC_DRIVER)" is not a valid Haptic driver)
+ else
+ OPT_DEFS += -DHAPTIC_$(strip $(shell echo $(HAPTIC_DRIVER) | tr '[:lower:]' '[:upper:]'))
+ COMMON_VPATH += $(DRIVER_PATH)/haptic
- ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), )
- SRC += DRV2605L.c
- QUANTUM_LIB_SRC += i2c_master.c
- OPT_DEFS += -DDRV2605L
- endif
+ ifeq ($(strip $(HAPTIC_DRIVER)), drv2605l)
+ I2C_DRIVER_REQUIRED = yes
+ SRC += drv2605l.c
+ endif
- ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), )
- SRC += solenoid.c
- OPT_DEFS += -DSOLENOID_ENABLE
+ ifeq ($(strip $(HAPTIC_DRIVER)), solenoid)
+ SRC += solenoid.c
+ endif
endif
endif
@@ -742,8 +736,8 @@ ifeq ($(strip $(HD44780_ENABLE)), yes)
SRC += hd44780.c
endif
-VALID_OLED_DRIVER_TYPES := SSD1306 custom
-OLED_DRIVER ?= SSD1306
+VALID_OLED_DRIVER_TYPES := custom ssd1306
+OLED_DRIVER ?= ssd1306
VALID_OLED_TRANSPORT_TYPES := i2c spi custom
OLED_TRANSPORT ?= i2c
ifeq ($(strip $(OLED_ENABLE)), yes)
@@ -754,6 +748,7 @@ ifeq ($(strip $(OLED_ENABLE)), yes)
$(call CATASTROPHIC_ERROR,Invalid OLED_TRANSPORT,OLED_TRANSPORT="$(OLED_TRANSPORT)" is not a valid OLED transport)
else
OPT_DEFS += -DOLED_ENABLE
+ OPT_DEFS += -DOLED_$(strip $(shell echo $(OLED_DRIVER) | tr '[:lower:]' '[:upper:]'))
COMMON_VPATH += $(DRIVER_PATH)/oled
ifneq ($(strip $(OLED_DRIVER)), custom)
SRC += oled_driver.c
@@ -761,10 +756,10 @@ ifeq ($(strip $(OLED_ENABLE)), yes)
OPT_DEFS += -DOLED_TRANSPORT_$(strip $(shell echo $(OLED_TRANSPORT) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(OLED_TRANSPORT)), i2c)
- QUANTUM_LIB_SRC += i2c_master.c
+ I2C_DRIVER_REQUIRED = yes
endif
ifeq ($(strip $(OLED_TRANSPORT)), spi)
- QUANTUM_LIB_SRC += spi_master.c
+ SPI_DRIVER_REQUIRED = yes
endif
endif
endif
@@ -772,22 +767,24 @@ endif
ifeq ($(strip $(ST7565_ENABLE)), yes)
OPT_DEFS += -DST7565_ENABLE
+ SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h
COMMON_VPATH += $(DRIVER_PATH)/lcd
- QUANTUM_LIB_SRC += spi_master.c
SRC += st7565.c
endif
ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE
UNICODE_COMMON := yes
- SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c
+ SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c \
+ $(QUANTUM_DIR)/unicode/ucis.c
endif
ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
OPT_DEFS += -DUNICODEMAP_ENABLE
UNICODE_COMMON := yes
- SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c
+ SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c \
+ $(QUANTUM_DIR)/unicode/unicodemap.c
endif
ifeq ($(strip $(UNICODE_ENABLE)), yes)
@@ -804,27 +801,6 @@ ifeq ($(strip $(UNICODE_COMMON)), yes)
$(QUANTUM_DIR)/unicode/utf8.c
endif
-MAGIC_ENABLE ?= yes
-ifeq ($(strip $(MAGIC_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_magic.c
- OPT_DEFS += -DMAGIC_KEYCODE_ENABLE
-endif
-
-SEND_STRING_ENABLE ?= yes
-ifeq ($(strip $(SEND_STRING_ENABLE)), yes)
- OPT_DEFS += -DSEND_STRING_ENABLE
- COMMON_VPATH += $(QUANTUM_DIR)/send_string
- SRC += $(QUANTUM_DIR)/send_string/send_string.c
-endif
-
-ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
- OPT_DEFS += -DAUTO_SHIFT_ENABLE
- ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
- OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
- endif
-endif
-
ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
PS2_ENABLE := yes
MOUSE_ENABLE := yes
@@ -865,8 +841,8 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/joystick.c
ifeq ($(strip $(JOYSTICK_DRIVER)), analog)
+ ANALOG_DRIVER_REQUIRED = yes
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE
- SRC += analog.c
endif
ifeq ($(strip $(JOYSTICK_DRIVER)), digital)
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
@@ -898,29 +874,28 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
endif
BLUETOOTH_ENABLE ?= no
-VALID_BLUETOOTH_DRIVER_TYPES := BluefruitLE RN42 custom
+VALID_BLUETOOTH_DRIVER_TYPES := bluefruit_le custom rn42
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid BLUETOOTH_DRIVER,BLUETOOTH_DRIVER="$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type)
endif
OPT_DEFS += -DBLUETOOTH_ENABLE
+ OPT_DEFS += -DBLUETOOTH_$(strip $(shell echo $(BLUETOOTH_DRIVER) | tr '[:lower:]' '[:upper:]'))
NO_USB_STARTUP_CHECK := yes
COMMON_VPATH += $(DRIVER_PATH)/bluetooth
SRC += outputselect.c
- ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE)
- OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE
+ ifeq ($(strip $(BLUETOOTH_DRIVER)), bluefruit_le)
+ SPI_DRIVER_REQUIRED = yes
+ ANALOG_DRIVER_REQUIRED = yes
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
- QUANTUM_LIB_SRC += analog.c
- QUANTUM_LIB_SRC += spi_master.c
endif
- ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42)
- OPT_DEFS += -DBLUETOOTH_RN42 -DHAL_USE_SERIAL=TRUE
+ ifeq ($(strip $(BLUETOOTH_DRIVER)), rn42)
+ UART_DRIVER_REQUIRED = yes
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
SRC += $(DRIVER_PATH)/bluetooth/rn42.c
- QUANTUM_LIB_SRC += uart.c
endif
endif
@@ -932,10 +907,51 @@ ifeq ($(strip $(ENCODER_ENABLE)), yes)
endif
endif
-ifeq ($(strip $(OS_DETECTION_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/os_detection.c
- OPT_DEFS += -DOS_DETECTION_ENABLE
- ifeq ($(strip $(OS_DETECTION_DEBUG_ENABLE)), yes)
- OPT_DEFS += -DOS_DETECTION_DEBUG_ENABLE
+VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
+
+WS2812_DRIVER ?= bitbang
+ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
+ ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),)
+ $(call CATASTROPHIC_ERROR,Invalid WS2812_DRIVER,WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver)
endif
+
+ OPT_DEFS += -DWS2812_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))
+
+ SRC += ws2812_$(strip $(WS2812_DRIVER)).c
+
+ ifeq ($(strip $(PLATFORM)), CHIBIOS)
+ ifeq ($(strip $(WS2812_DRIVER)), pwm)
+ OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
+ endif
+ endif
+
+ # add extra deps
+ ifeq ($(strip $(WS2812_DRIVER)), i2c)
+ I2C_DRIVER_REQUIRED = yes
+ endif
+endif
+
+ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
+ COMMON_VPATH += $(DRIVER_PATH)/led
+ SRC += apa102.c
+endif
+
+ifeq ($(strip $(ANALOG_DRIVER_REQUIRED)), yes)
+ OPT_DEFS += -DHAL_USE_ADC=TRUE
+ QUANTUM_LIB_SRC += analog.c
+endif
+
+ifeq ($(strip $(I2C_DRIVER_REQUIRED)), yes)
+ OPT_DEFS += -DHAL_USE_I2C=TRUE
+ QUANTUM_LIB_SRC += i2c_master.c
+endif
+
+ifeq ($(strip $(SPI_DRIVER_REQUIRED)), yes)
+ OPT_DEFS += -DHAL_USE_SPI=TRUE
+ QUANTUM_LIB_SRC += spi_master.c
+endif
+
+ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes)
+ OPT_DEFS += -DHAL_USE_SERIAL=TRUE
+ QUANTUM_LIB_SRC += uart.c
endif
diff --git a/builddefs/common_rules.mk b/builddefs/common_rules.mk
index 816eac49ae8f..cfd261737c06 100644
--- a/builddefs/common_rules.mk
+++ b/builddefs/common_rules.mk
@@ -12,6 +12,9 @@ vpath %.hpp $(VPATH_SRC)
vpath %.S $(VPATH_SRC)
VPATH :=
+# Helper to return the distinct elements of a list
+uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
+
# Convert all SRC to OBJ
define OBJ_FROM_SRC
$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$(patsubst %.clib,$1/%.a,$($1_SRC))))))
@@ -176,7 +179,7 @@ MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
# For a ChibiOS build, ensure that the board files have the hook overrides injected
define BOARDSRC_INJECT_HOOKS
-$(KEYBOARD_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h
+$(INTERMEDIATE_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h
endef
$(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ))))
@@ -188,7 +191,7 @@ DFU_SUFFIX_ARGS ?=
elf: $(BUILD_DIR)/$(TARGET).elf
hex: $(BUILD_DIR)/$(TARGET).hex
uf2: $(BUILD_DIR)/$(TARGET).uf2
-cpfirmware: $(FIRMWARE_FORMAT)
+cpfirmware_qmk: $(FIRMWARE_FORMAT)
$(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD)
$(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK)
eep: $(BUILD_DIR)/$(TARGET).eep
@@ -197,6 +200,15 @@ sym: $(BUILD_DIR)/$(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)
+cpfirmware: cpfirmware_qmk
+
+ifneq ($(QMK_USERSPACE),)
+cpfirmware: cpfirmware_userspace
+cpfirmware_userspace: cpfirmware_qmk
+ $(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to userspace folder" | $(AWK_CMD)
+ $(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(QMK_USERSPACE)/$(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK)
+endif
+
# Display size of file, modifying the output so people don't mistakenly grab the hex output
BINARY_SIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(SED) -e 's/\.build\/.*$$/$(TARGET).$(FIRMWARE_FORMAT)/g'
@@ -264,7 +276,7 @@ BEGIN = gccversion sizebefore
# Note the obj.txt depeendency is there to force linking if a source file is deleted
%.elf: $(OBJ) $(MASTER_OUTPUT)/cflags.txt $(MASTER_OUTPUT)/ldflags.txt $(MASTER_OUTPUT)/obj.txt | $(BEGIN)
@$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD)
- $(eval CMD=MAKE=$(MAKE) $(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS))
+ $(eval CMD=MAKE=$(MAKE) $(CC) $(ALL_CFLAGS) $(call uniq,$(OBJ)) --output $@ $(LDFLAGS))
@$(BUILD_CMD)
@@ -380,31 +392,9 @@ dump_vars:
objs-size:
for i in $(OBJ); do echo $$i; done | sort | xargs $(SIZE)
-ifeq ($(findstring avr-gcc,$(CC)),avr-gcc)
-SIZE_MARGIN = 1024
+# size check optionally implemented in its platform.mk
check-size:
- $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | $(SED) -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
- $(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi))
- $(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE)))
- $(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE)))
- $(eval PERCENT_SIZE=$(shell expr $(CURRENT_SIZE) \* 100 / $(MAX_SIZE)))
- if [ $(MAX_SIZE) -gt 0 ] && [ $(CURRENT_SIZE) -gt 0 ]; then \
- $(SILENT) || printf "$(MSG_CHECK_FILESIZE)" | $(AWK_CMD); \
- if [ $(CURRENT_SIZE) -gt $(MAX_SIZE) ]; then \
- printf "\n * $(MSG_FILE_TOO_BIG)"; $(PRINT_ERROR_PLAIN); \
- else \
- if [ $(FREE_SIZE) -lt $(SIZE_MARGIN) ]; then \
- $(PRINT_WARNING_PLAIN); printf " * $(MSG_FILE_NEAR_LIMIT)"; \
- else \
- $(PRINT_OK); $(SILENT) || printf " * $(MSG_FILE_JUST_RIGHT)"; \
- fi ; \
- fi ; \
- fi
-else
-check-size:
- $(SILENT) || echo "$(MSG_CHECK_FILESIZE_SKIPPED)"
-endif
check-md5:
$(MD5SUM) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT)
diff --git a/builddefs/converters.mk b/builddefs/converters.mk
index a3548afd609f..96c8656b253f 100644
--- a/builddefs/converters.mk
+++ b/builddefs/converters.mk
@@ -25,7 +25,9 @@ ifneq ($(CONVERT_TO),)
-include $(CONVERTER)/pre_converter.mk
PLATFORM_KEY = $(shell echo $(CONVERTER) | cut -d "/" -f2)
- TARGET := $(TARGET)_$(CONVERT_TO)
+
+ # force setting as value can be from environment
+ override TARGET := $(TARGET)_$(CONVERT_TO)
# Configure any defaults
OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]')
diff --git a/builddefs/generic_features.mk b/builddefs/generic_features.mk
index 4e058dcd2659..9c8695862554 100644
--- a/builddefs/generic_features.mk
+++ b/builddefs/generic_features.mk
@@ -13,39 +13,52 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-SPACE_CADET_ENABLE ?= yes
GRAVE_ESC_ENABLE ?= yes
+MAGIC_ENABLE ?= yes
+SEND_STRING_ENABLE ?= yes
+SPACE_CADET_ENABLE ?= yes
GENERIC_FEATURES = \
+ AUTO_SHIFT \
AUTOCORRECT \
CAPS_WORD \
COMBO \
COMMAND \
+ CRC \
DEFERRED_EXEC \
DIGITIZER \
DIP_SWITCH \
DYNAMIC_KEYMAP \
DYNAMIC_MACRO \
+ DYNAMIC_TAPPING_TERM \
GRAVE_ESC \
HAPTIC \
KEY_LOCK \
KEY_OVERRIDE \
LEADER \
+ MAGIC \
+ MOUSEKEY \
+ MUSIC \
+ OS_DETECTION \
PROGRAMMABLE_BUTTON \
REPEAT_KEY \
SECURE \
+ SEND_STRING \
+ SEQUENCER \
SPACE_CADET \
SWAP_HANDS \
TAP_DANCE \
- VELOCIKEY \
+ TRI_LAYER \
+ VIA \
+ VIRTSER \
WPM \
- DYNAMIC_TAPPING_TERM \
- TRI_LAYER
define HANDLE_GENERIC_FEATURE
# $$(info "Processing: $1_ENABLE $2.c")
SRC += $$(wildcard $$(QUANTUM_DIR)/process_keycode/process_$2.c)
+ SRC += $$(wildcard $$(QUANTUM_DIR)/$2/$2.c)
SRC += $$(wildcard $$(QUANTUM_DIR)/$2.c)
+ VPATH += $$(wildcard $$(QUANTUM_DIR)/$2/)
OPT_DEFS += -D$1_ENABLE
endef
diff --git a/builddefs/message.mk b/builddefs/message.mk
index bf39554dab77..7c8f87f99006 100644
--- a/builddefs/message.mk
+++ b/builddefs/message.mk
@@ -91,7 +91,6 @@ MSG_AVAILABLE_KEYMAPS = $(eval $(call GENERATE_MSG_AVAILABLE_KEYMAPS))$(MSG_AVAI
MSG_BOOTLOADER_NOT_FOUND_BASE = Bootloader not found. Make sure the board is in bootloader mode. See https://docs.qmk.fm/\#/newbs_flashing\n
MSG_CHECK_FILESIZE = Checking file size of $(TARGET).$(FIRMWARE_FORMAT)
-MSG_CHECK_FILESIZE_SKIPPED = (Firmware size check does not yet support $(MCU_ORIG); skipping)
MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT_SIZE)/$(MAX_SIZE) ($(OVER_SIZE) bytes over)\n
MSG_FILE_TOO_SMALL = The firmware is too small! $(CURRENT_SIZE)/$(MAX_SIZE)\n
MSG_FILE_JUST_RIGHT = The firmware size is fine - $(CURRENT_SIZE)/$(MAX_SIZE) ($(PERCENT_SIZE)%%, $(FREE_SIZE) bytes free)\n
@@ -104,6 +103,10 @@ MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) $(MSG_BOOTLOADER_NOT_
BOOTLOADER_RETRY_TIME ?= 0.5
MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = $(MSG_BOOTLOADER_NOT_FOUND_BASE) Trying again every $(BOOTLOADER_RETRY_TIME)s (Ctrl+C to cancel)
+define WARNING_MESSAGE
+ $(shell printf "\n %-99s $(WARN_STRING)\n" "$1" >&2)
+endef
+
define CATASTROPHIC_ERROR
$(shell printf "\n * %-99s $(ERROR_STRING)\n" "$2" >&2)
$(error $1)
diff --git a/builddefs/show_options.mk b/builddefs/show_options.mk
index 8bcc02083bc5..81d8400a8064 100644
--- a/builddefs/show_options.mk
+++ b/builddefs/show_options.mk
@@ -17,7 +17,7 @@ HARDWARE_OPTION_NAMES = \
BACKLIGHT_ENABLE \
BACKLIGHT_DRIVER \
RGBLIGHT_ENABLE \
- RGBLIGHT_CUSTOM_DRIVER \
+ RGBLIGHT_DRIVER \
RGB_MATRIX_ENABLE \
RGB_MATRIX_DRIVER \
CIE1931_CURVE \
@@ -37,7 +37,6 @@ OTHER_OPTION_NAMES = \
UNICODEMAP_ENABLE \
UNICODE_COMMON \
AUTO_SHIFT_ENABLE \
- AUTO_SHIFT_MODIFIERS \
DYNAMIC_TAPPING_TERM_ENABLE \
COMBO_ENABLE \
KEY_LOCK_ENABLE \
@@ -60,8 +59,6 @@ OTHER_OPTION_NAMES = \
ENCODER_ENABLE_CUSTOM \
GERMAN_ENABLE \
HAPTIC_ENABLE \
- HHKB_RN42_ENABLE \
- ISSI_ENABLE \
KEYLOGGER_ENABLE \
LCD_BACKLIGHT_ENABLE \
MACROS_ENABLED \
diff --git a/data/constants/keycodes/extras/keycodes_russian_typewriter_0.0.1.hjson b/data/constants/keycodes/extras/keycodes_russian_typewriter_0.0.1.hjson
new file mode 100644
index 000000000000..6ad03c58e555
--- /dev/null
+++ b/data/constants/keycodes/extras/keycodes_russian_typewriter_0.0.1.hjson
@@ -0,0 +1,291 @@
+{
+ "aliases": {
+/*
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ | │ № │ - │ / │ " │ : │ , │ . │ _ │ ? │ % │ ! │ ; │ │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │ │ Й │ Ц │ У │ К │ Е │ Н │ Г │ Ш │ Щ │ З │ Х │ Ъ │ ) │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
+ * │ │ Ф │ Ы │ В │ А │ П │ Р │ О │ Л │ Д │ Ж │ Э │ │
+ * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
+ * │ │ Я │ Ч │ С │ М │ И │ Т │ Ь │ Б │ Ю │ Ё │ │
+ * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │ │ │ │ │ │ │ │ │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+ "KC_GRV": {
+ "key": "RU_PIPE",
+ "label": "|",
+ }
+ "KC_1": {
+ "key": "RU_NUM",
+ "label": "№",
+ }
+ "KC_2": {
+ "key": "RU_MINS",
+ "label": "-",
+ }
+ "KC_3": {
+ "key": "RU_SLSH",
+ "label": "/",
+ }
+ "KC_4": {
+ "key": "RU_DQUO",
+ "label": "\"",
+ }
+ "KC_5": {
+ "key": "RU_COLN",
+ "label": ":",
+ }
+ "KC_6": {
+ "key": "RU_COMM",
+ "label": ",",
+ }
+ "KC_7": {
+ "key": "RU_DOT",
+ "label": ".",
+ }
+ "KC_8": {
+ "key": "RU_UNDS",
+ "label": "_",
+ }
+ "KC_9": {
+ "key": "RU_QUES",
+ "label": "?",
+ }
+ "KC_0": {
+ "key": "RU_PERC",
+ "label": "%",
+ }
+ "KC_MINS": {
+ "key": "RU_EXLM",
+ "label": "!",
+ }
+ "KC_EQL": {
+ "key": "RU_SCLN",
+ "label": ";",
+ }
+ "KC_Q": {
+ "key": "RU_SHTI",
+ "label": "Й",
+ }
+ "KC_W": {
+ "key": "RU_TSE",
+ "label": "Ц",
+ }
+ "KC_E": {
+ "key": "RU_U",
+ "label": "У",
+ }
+ "KC_R": {
+ "key": "RU_KA",
+ "label": "К",
+ }
+ "KC_T": {
+ "key": "RU_IE",
+ "label": "Е",
+ }
+ "KC_Y": {
+ "key": "RU_EN",
+ "label": "Н",
+ }
+ "KC_U": {
+ "key": "RU_GHE",
+ "label": "Г",
+ }
+ "KC_I": {
+ "key": "RU_SHA",
+ "label": "Ш",
+ }
+ "KC_O": {
+ "key": "RU_SHCH",
+ "label": "Щ",
+ }
+ "KC_P": {
+ "key": "RU_ZE",
+ "label": "З",
+ }
+ "KC_LBRC": {
+ "key": "RU_HA",
+ "label": "Х",
+ }
+ "KC_RBRC": {
+ "key": "RU_HARD",
+ "label": "Ъ",
+ }
+ "KC_BSLS": {
+ "key": "RU_RPRN",
+ "label": ")",
+ }
+ "KC_A": {
+ "key": "RU_EF",
+ "label": "Ф",
+ }
+ "KC_S": {
+ "key": "RU_YERU",
+ "label": "Ы",
+ }
+ "KC_D": {
+ "key": "RU_VE",
+ "label": "В",
+ }
+ "KC_F": {
+ "key": "RU_A",
+ "label": "А",
+ }
+ "KC_G": {
+ "key": "RU_PE",
+ "label": "П",
+ }
+ "KC_H": {
+ "key": "RU_ER",
+ "label": "Р",
+ }
+ "KC_J": {
+ "key": "RU_O",
+ "label": "О",
+ }
+ "KC_K": {
+ "key": "RU_EL",
+ "label": "Л",
+ }
+ "KC_L": {
+ "key": "RU_DE",
+ "label": "Д",
+ }
+ "KC_SCLN": {
+ "key": "RU_ZHE",
+ "label": "Ж",
+ }
+ "KC_QUOT": {
+ "key": "RU_E",
+ "label": "Э",
+ }
+ "KC_Z": {
+ "key": "RU_YA",
+ "label": "Я",
+ }
+ "KC_X": {
+ "key": "RU_CHE",
+ "label": "Ч",
+ }
+ "KC_C": {
+ "key": "RU_ES",
+ "label": "С",
+ }
+ "KC_V": {
+ "key": "RU_EM",
+ "label": "М",
+ }
+ "KC_B": {
+ "key": "RU_I",
+ "label": "И",
+ }
+ "KC_N": {
+ "key": "RU_TE",
+ "label": "Т",
+ }
+ "KC_M": {
+ "key": "RU_SOFT",
+ "label": "Ь",
+ }
+ "KC_COMM": {
+ "key": "RU_BE",
+ "label": "Б",
+ }
+ "KC_DOT": {
+ "key": "RU_YU",
+ "label": "Ю",
+ }
+ "KC_SLSH": {
+ "key": "RU_YO",
+ "label": "Ё",
+ }
+/* Shifted symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ + │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ = │ \ │ │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │ ( │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │ │ │ │ │ │ │ │ │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+ "S(RU_PIPE)": {
+ "key": "RU_PLUS",
+ "label": "+",
+ }
+ "S(RU_NUM)": {
+ "key": "RU_1",
+ "label": "1",
+ }
+ "S(RU_MINS)": {
+ "key": "RU_2",
+ "label": "2",
+ }
+ "S(RU_SLSH)": {
+ "key": "RU_3",
+ "label": "3",
+ }
+ "S(RU_DQUO)": {
+ "key": "RU_4",
+ "label": "4",
+ }
+ "S(RU_COLN)": {
+ "key": "RU_5",
+ "label": "5",
+ }
+ "S(RU_COMM)": {
+ "key": "RU_6",
+ "label": "6",
+ }
+ "S(RU_DOT)": {
+ "key": "RU_7",
+ "label": "7",
+ }
+ "S(RU_UNDS)": {
+ "key": "RU_8",
+ "label": "8",
+ }
+ "S(RU_QUES)": {
+ "key": "RU_9",
+ "label": "9",
+ }
+ "S(RU_PERC)": {
+ "key": "RU_0",
+ "label": "0",
+ }
+ "S(RU_EXLM)": {
+ "key": "RU_EQL",
+ "label": "=",
+ }
+ "S(RU_SCLN)": {
+ "key": "RU_BSLS",
+ "label": "\\",
+ }
+ "S(RU_RPRN)": {
+ "key": "RU_LPRN",
+ "label": "(",
+ }
+/* AltGr symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ │ │ │ │ │ │ │ │ ₽ │ │ │ │ │ │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
+ * │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │ │ │ │ │ │ │ │ │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+ "ALGR(RU_UNDS)": {
+ "key": "RU_RUBL",
+ "label": "₽",
+ }
+ }
+}
diff --git a/data/mappings/defaults.hjson b/data/mappings/defaults.hjson
index 2bb00da22362..4a9f06c0da58 100644
--- a/data/mappings/defaults.hjson
+++ b/data/mappings/defaults.hjson
@@ -1,84 +1,84 @@
{
"development_board": {
- "promicro": {
- "processor": "atmega32u4",
- "bootloader": "caterina",
- "pin_compatible": "promicro"
+ "bit_c_pro": {
+ "board": "QMK_PM2040",
+ "bootloader": "rp2040",
+ "processor": "RP2040"
},
- "elite_c": {
- "processor": "atmega32u4",
- "bootloader": "atmel-dfu",
- "pin_compatible": "promicro"
+ "blackpill_f401": {
+ "board": "BLACKPILL_STM32_F401",
+ "bootloader": "stm32-dfu",
+ "processor": "STM32F401"
},
- "elite_pi": {
- "processor": "RP2040",
+ "blackpill_f411": {
+ "board": "BLACKPILL_STM32_F411",
+ "bootloader": "stm32-dfu",
+ "processor": "STM32F411"
+ },
+ "blok": {
+ "board": "QMK_BLOK",
"bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "RP2040"
},
- "proton_c": {
- "processor": "STM32F303",
+ "bluepill": {
+ "board": "STM32_F103_STM32DUINO",
+ "bootloader": "stm32duino",
+ "processor": "STM32F103"
+ },
+ "bonsai_c4": {
+ "board": "BONSAI_C4",
"bootloader": "stm32-dfu",
- "board": "QMK_PROTON_C"
+ "processor": "STM32F411"
},
- "kb2040": {
- "processor": "RP2040",
+ "elite_c": {
+ "bootloader": "atmel-dfu",
+ "pin_compatible": "promicro",
+ "processor": "atmega32u4"
+ },
+ "elite_pi": {
+ "board": "QMK_PM2040",
"bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "RP2040"
},
- "promicro_rp2040": {
- "processor": "RP2040",
+ "helios": {
+ "board": "QMK_PM2040",
"bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "RP2040"
},
- "blok": {
- "processor": "RP2040",
+ "kb2040": {
+ "board": "QMK_PM2040",
"bootloader": "rp2040",
- "board": "QMK_BLOK"
+ "processor": "RP2040"
},
- "michi": {
- "processor": "RP2040",
+ "liatris": {
+ "board": "QMK_PM2040",
"bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "RP2040"
},
- "bit_c_pro": {
- "processor": "RP2040",
+ "michi": {
+ "board": "QMK_PM2040",
"bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "RP2040"
},
- "bluepill": {
- "processor": "STM32F103",
- "bootloader": "stm32duino",
- "board": "STM32_F103_STM32DUINO"
+ "promicro": {
+ "bootloader": "caterina",
+ "pin_compatible": "promicro",
+ "processor": "atmega32u4"
},
- "blackpill_f401": {
- "processor": "STM32F401",
- "bootloader": "stm32-dfu",
- "board": "BLACKPILL_STM32_F401"
+ "promicro_rp2040": {
+ "board": "QMK_PM2040",
+ "bootloader": "rp2040",
+ "processor": "RP2040"
},
- "blackpill_f411": {
- "processor": "STM32F411",
+ "proton_c": {
+ "board": "QMK_PROTON_C",
"bootloader": "stm32-dfu",
- "board": "BLACKPILL_STM32_F411"
+ "processor": "STM32F303"
},
"stemcell": {
- "processor": "STM32F411",
+ "board": "STEMCELL",
"bootloader": "tinyuf2",
- "board": "STEMCELL"
- },
- "bonsai_c4": {
- "processor": "STM32F411",
- "bootloader": "stm32-dfu",
- "board": "BONSAI_C4"
- },
- "helios": {
- "processor": "RP2040",
- "bootloader": "rp2040",
- "board": "QMK_PM2040"
- },
- "liatris": {
- "processor": "RP2040",
- "bootloader": "rp2040",
- "board": "QMK_PM2040"
+ "processor": "STM32F411"
}
}
}
diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson
index e53d90da39b3..26b437b51335 100644
--- a/data/mappings/info_config.hjson
+++ b/data/mappings/info_config.hjson
@@ -29,6 +29,9 @@
"BACKLIGHT_PIN": {"info_key": "backlight.pin"},
"BACKLIGHT_PINS": {"info_key": "backlight.pins", "value_type": "array"},
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
+ "BACKLIGHT_DEFAULT_ON": {"info_key": "backlight.default.on", "value_type": "bool"},
+ "BACKLIGHT_DEFAULT_BREATHING": {"info_key": "backlight.default.breathing", "value_type": "bool"},
+ "BACKLIGHT_DEFAULT_LEVEL": {"info_key": "backlight.default.brightness", "value_type": "int"},
// Bootmagic
"BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"},
@@ -45,10 +48,18 @@
// Combos
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
+ "DIP_SWITCH_MATRIX_GRID": {"info_key": "dip_switch.matrix_grid", "value_type": "array.array.int", "to_json": false},
+ "DIP_SWITCH_PINS": {"info_key": "dip_switch.pins", "value_type": "array"},
+ "DIP_SWITCH_PINS_RIGHT": {"info_key": "split.dip_switch.right.pins", "value_type": "array"},
+
// Dynamic Keymap
"DYNAMIC_KEYMAP_EEPROM_MAX_ADDR": {"info_key": "dynamic_keymap.eeprom_max_addr", "value_type": "int"},
"DYNAMIC_KEYMAP_LAYER_COUNT": {"info_key": "dynamic_keymap.layer_count", "value_type": "int"},
+ // EEPROM
+ "WEAR_LEVELING_BACKING_SIZE": {"info_key": "eeprom.wear_leveling.backing_size", "value_type": "int", "to_json": false},
+ "WEAR_LEVELING_LOGICAL_SIZE": {"info_key": "eeprom.wear_leveling.logical_size", "value_type": "int", "to_json": false},
+
// Indicators
"LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"},
"LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"},
@@ -63,14 +74,24 @@
"LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"},
// LED Matrix
+ "LED_DISABLE_WHEN_USB_SUSPENDED": {"info_key": "led_matrix.sleep", "value_type": "bool"},
"LED_MATRIX_CENTER": {"info_key": "led_matrix.center_point", "value_type": "array.int"},
- "LED_MATRIX_HUE_STEP": {"info_key": "led_matrix.hue_steps", "value_type": "int"},
+ "LED_MATRIX_KEYRELEASES": {"info_key": "led_matrix.react_on_keyup", "value_type": "bool"},
+ "LED_MATRIX_LED_FLUSH_LIMIT": {"info_key": "led_matrix.led_flush_limit", "value_type": "int"},
+ "LED_MATRIX_LED_PROCESS_LIMIT": {"info_key": "led_matrix.led_process_limit", "value_type": "int", "to_json": false},
"LED_MATRIX_MAXIMUM_BRIGHTNESS": {"info_key": "led_matrix.max_brightness", "value_type": "int"},
- "LED_MATRIX_SAT_STEP": {"info_key": "led_matrix.sat_steps", "value_type": "int"},
"LED_MATRIX_SPD_STEP": {"info_key": "led_matrix.speed_steps", "value_type": "int"},
"LED_MATRIX_SPLIT": {"info_key": "led_matrix.split_count", "value_type": "array.int"},
"LED_MATRIX_TIMEOUT": {"info_key": "led_matrix.timeout", "value_type": "int"},
"LED_MATRIX_VAL_STEP": {"info_key": "led_matrix.val_steps", "value_type": "int"},
+ "LED_MATRIX_LED_COUNT": {"info_key": "led_matrix.led_count", "value_type": "int", "to_json": false},
+ "LED_MATRIX_DEFAULT_ON": {"info_key": "led_matrix.default.on", "value_type": "bool"},
+ "LED_MATRIX_DEFAULT_VAL": {"info_key": "led_matrix.default.val", "value_type": "int"},
+ "LED_MATRIX_DEFAULT_SPD": {"info_key": "led_matrix.default.speed", "value_type": "int"},
+
+ // Locking Switch
+ "LOCKING_SUPPORT_ENABLE": {"info_key": "qmk.locking.enabled", "value_type": "bool"},
+ "LOCKING_RESYNC_ENABLE": {"info_key": "qmk.locking.resync", "value_type": "bool"},
// LUFA Bootloader
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
@@ -101,14 +122,24 @@
"PS2_DATA_PIN": {"info_key": "ps2.data_pin"},
// RGB Matrix
+ "RGB_DISABLE_WHEN_USB_SUSPENDED": {"info_key": "rgb_matrix.sleep", "value_type": "bool"},
"RGB_MATRIX_CENTER": {"info_key": "rgb_matrix.center_point", "value_type": "array.int"},
"RGB_MATRIX_HUE_STEP": {"info_key": "rgb_matrix.hue_steps", "value_type": "int"},
+ "RGB_MATRIX_KEYRELEASES": {"info_key": "rgb_matrix.react_on_keyup", "value_type": "bool"},
+ "RGB_MATRIX_LED_FLUSH_LIMIT": {"info_key": "rgb_matrix.led_flush_limit", "value_type": "int"},
+ "RGB_MATRIX_LED_PROCESS_LIMIT": {"info_key": "rgb_matrix.led_process_limit", "value_type": "int", "to_json": false},
"RGB_MATRIX_MAXIMUM_BRIGHTNESS": {"info_key": "rgb_matrix.max_brightness", "value_type": "int"},
"RGB_MATRIX_SAT_STEP": {"info_key": "rgb_matrix.sat_steps", "value_type": "int"},
"RGB_MATRIX_SPD_STEP": {"info_key": "rgb_matrix.speed_steps", "value_type": "int"},
"RGB_MATRIX_SPLIT": {"info_key": "rgb_matrix.split_count", "value_type": "array.int"},
"RGB_MATRIX_TIMEOUT": {"info_key": "rgb_matrix.timeout", "value_type": "int"},
"RGB_MATRIX_VAL_STEP": {"info_key": "rgb_matrix.val_steps", "value_type": "int"},
+ "RGB_MATRIX_LED_COUNT": {"info_key": "rgb_matrix.led_count", "value_type": "int", "to_json": false},
+ "RGB_MATRIX_DEFAULT_ON": {"info_key": "rgb_matrix.default.on", "value_type": "bool"},
+ "RGB_MATRIX_DEFAULT_HUE": {"info_key": "rgb_matrix.default.hue", "value_type": "int"},
+ "RGB_MATRIX_DEFAULT_SAT": {"info_key": "rgb_matrix.default.sat", "value_type": "int"},
+ "RGB_MATRIX_DEFAULT_VAL": {"info_key": "rgb_matrix.default.val", "value_type": "int"},
+ "RGB_MATRIX_DEFAULT_SPD": {"info_key": "rgb_matrix.default.speed", "value_type": "int"},
// RGBLight
"RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"},
@@ -117,12 +148,18 @@
"RGBLIGHT_LAYER_BLINK": {"info_key": "rgblight.layers.blink", "value_type": "bool"},
"RGBLIGHT_LAYERS": {"info_key": "rgblight.layers.enabled", "value_type": "bool"},
"RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF": {"info_key": "rgblight.layers.override_rgb", "value_type": "bool"},
+ "RGBLIGHT_LED_MAP": {"info_key": "rgblight.led_map", "value_type": "array.int"},
"RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"},
"RGBLIGHT_MAX_LAYERS": {"info_key": "rgblight.layers.max", "value_type": "int"},
"RGBLIGHT_SAT_STEP": {"info_key": "rgblight.saturation_steps", "value_type": "int"},
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"},
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"},
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
+ "RGBLIGHT_DEFAULT_ON": {"info_key": "rgblight.default.on", "value_type": "bool"},
+ "RGBLIGHT_DEFAULT_HUE": {"info_key": "rgblight.default.hue", "value_type": "int"},
+ "RGBLIGHT_DEFAULT_SAT": {"info_key": "rgblight.default.sat", "value_type": "int"},
+ "RGBLIGHT_DEFAULT_VAL": {"info_key": "rgblight.default.val", "value_type": "int"},
+ "RGBLIGHT_DEFAULT_SPD": {"info_key": "rgblight.default.speed", "value_type": "int"},
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
// Secure
@@ -133,13 +170,23 @@
// Split Keyboard
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
- "SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"},
- "SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"},
+ "SPLIT_HAND_MATRIX_GRID": {"info_key": "split.handedness.matrix_grid", "value_type": "array", "to_c": false},
+ "SPLIT_HAND_PIN": {"info_key": "split.handedness.pin"},
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
"SPLIT_USB_TIMEOUT": {"info_key": "split.usb_detect.timeout", "value_type": "int"},
"SPLIT_USB_TIMEOUT_POLL": {"info_key": "split.usb_detect.polling_interval", "value_type": "int"},
"SPLIT_WATCHDOG_ENABLE": {"info_key": "split.transport.watchdog", "value_type": "bool"},
"SPLIT_WATCHDOG_TIMEOUT": {"info_key": "split.transport.watchdog_timeout", "value_type": "int"},
+ "SPLIT_ACTIVITY_ENABLE": {"info_key": "split.transport.sync.activity", "value_type": "bool"},
+ "SPLIT_DETECTED_OS_ENABLE": {"info_key": "split.transport.sync.detected_os", "value_type": "bool"},
+ "SPLIT_HAPTIC_ENABLE": {"info_key": "split.transport.sync.haptic", "value_type": "bool"},
+ "SPLIT_LAYER_STATE_ENABLE": {"info_key": "split.transport.sync.layer_state", "value_type": "bool"},
+ "SPLIT_LED_STATE_ENABLE": {"info_key": "split.transport.sync.indicators", "value_type": "bool"},
+ "SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync.matrix_state", "value_type": "bool"},
+ "SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync.modifiers", "value_type": "bool"},
+ "SPLIT_OLED_ENABLE": {"info_key": "split.transport.sync.oled", "value_type": "bool"},
+ "SPLIT_ST7565_ENABLE": {"info_key": "split.transport.sync.st7565", "value_type": "bool"},
+ "SPLIT_WPM_ENABLE": {"info_key": "split.transport.sync.wpm", "value_type": "bool"},
// Tapping
"HOLD_ON_OTHER_KEY_PRESS": {"info_key": "tapping.hold_on_other_key_press", "value_type": "bool"},
@@ -189,4 +236,9 @@
"PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false, "value_type": "str", "deprecated": true, "replace_with": "`keyboard_name` in info.json"},
"PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.pid` in info.json"},
"VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.vid` in info.json"},
+
+ // Items we want flagged in lint
+ "VIAL_KEYBOARD_UID": {"info_key": "_invalid.vial_uid", "invalid": true},
+ "VIAL_UNLOCK_COMBO_COLS": {"info_key": "_invalid.vial_unlock_cols", "invalid": true},
+ "VIAL_UNLOCK_COMBO_ROWS": {"info_key": "_invalid.vial_unlock_rows", "invalid": true}
}
diff --git a/data/mappings/info_rules.hjson b/data/mappings/info_rules.hjson
index bf8ec05cb2ce..02fc2bee9de6 100644
--- a/data/mappings/info_rules.hjson
+++ b/data/mappings/info_rules.hjson
@@ -17,6 +17,7 @@
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
"BOOTMAGIC_ENABLE": {"info_key": "bootmagic.enabled", "value_type": "bool"},
"CAPS_WORD_ENABLE": {"info_key": "caps_word.enabled", "value_type": "bool"},
+ "DIP_SWITCH_ENABLE": {"info_key": "dip_switch.enabled", "value_type": "bool"},
"DEBOUNCE_TYPE": {"info_key": "build.debounce_type"},
"EEPROM_DRIVER": {"info_key": "eeprom.driver"},
"ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
@@ -35,12 +36,14 @@
"PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
"PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
"RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"},
+ "RGBLIGHT_DRIVER": {"info_key": "rgblight.driver"},
"SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"},
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false},
"STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"},
"STENO_PROTOCOL": {"info_key": "stenography.protocol"},
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"},
+ "WEAR_LEVELING_DRIVER": {"info_key": "eeprom.wear_leveling.driver"},
"WS2812_DRIVER": {"info_key": "ws2812.driver"},
// Items we want flagged in lint
diff --git a/data/mappings/keyboard_aliases.hjson b/data/mappings/keyboard_aliases.hjson
index f1c1f81e9ad6..90f32ee6acca 100644
--- a/data/mappings/keyboard_aliases.hjson
+++ b/data/mappings/keyboard_aliases.hjson
@@ -1,13 +1,16 @@
{
// Format for each entry:
// "": {
- // "target": "",
- // "layouts": {
- // "": ""
- // }
+ // "target": ""
// }
//
- // Both target and layouts are optional.
+
+ /* This list of aliases is for testing purposes -- ensures "linked list" recursive traversal works correctly. */
+ "_test_a": { "target": "_test_b" },
+ "_test_b": { "target": "_test_c" },
+ "_test_c": { "target": "planck/rev6" },
+
+ /* The main list of aliases for moved keyboards within QMK. */
"2_milk": {
"target": "spaceman/2_milk"
},
@@ -39,7 +42,7 @@
"target": "amjkeyboard/amjpad"
},
"angel64": {
- "target": "angel64/alpha"
+ "target": "kakunpc/angel64/alpha"
},
"ashpil/modelm_usbc": {
"target": "ibm/model_m/ashpil_usbc"
@@ -51,10 +54,10 @@
"target": "viktus/at101_bh"
},
"atom47/rev2": {
- "target": "maartenwut/atom47/rev2"
+ "target": "evyd13/atom47/rev2"
},
"atom47/rev3": {
- "target": "maartenwut/atom47/rev3"
+ "target": "evyd13/atom47/rev3"
},
"bakeneko60": {
"target": "kkatano/bakeneko60"
@@ -69,7 +72,7 @@
"target": "bear_face/v1"
},
"bm16a": {
- "target": "kprepublic/bm16a"
+ "target": "kprepublic/bm16a/v1"
},
"bm16s": {
"target": "kprepublic/bm16s"
@@ -81,16 +84,16 @@
"target": "kprepublic/bm43a"
},
"bm60poker": {
- "target": "kprepublic/bm60poker"
+ "target": "kprepublic/bm60hsrgb_poker/rev1"
},
"bm60rgb": {
- "target": "kprepublic/bm60rgb"
+ "target": "kprepublic/bm60hsrgb/rev1"
},
"bm60rgb_iso": {
- "target": "kprepublic/bm60rgb_iso"
+ "target": "kprepublic/bm60hsrgb_iso/rev1"
},
"bm68rgb": {
- "target": "kprepublic/bm68rgb"
+ "target": "kprepublic/bm68hsrgb/rev1"
},
"bpiphany/pegasushoof": {
"target": "bpiphany/pegasushoof/2013"
@@ -140,26 +143,17 @@
"daisy": {
"target": "ktec/daisy"
},
- "doro67/multi": {
- "layouts": {
- "LAYOUT_ansi": "LAYOUT_65_ansi_blocker"
- }
- },
- "doro67/regular": {
- "layouts": {
- "LAYOUT": "LAYOUT_65_ansi_blocker"
- }
- },
- "doro67/rgb": {
- "layouts": {
- "LAYOUT": "LAYOUT_65_ansi_blocker"
- }
+ "dp3000": {
+ "target": "dp3000/rev1"
},
"drakon": {
"target": "jagdpietr/drakon"
},
"durgod/k320": {
- "target": "durgod/k3x0/k320"
+ "target": "durgod/k320/base"
+ },
+ "durgod/k3x0/k320": {
+ "target": "durgod/k320/base"
},
"durgod/hades": {
"target": "durgod/dgk6x/hades_ansi"
@@ -185,6 +179,9 @@
"dztech/volcano660": {
"target": "ilumkb/volcano660"
},
+ "dztech/og60": {
+ "target": "dztech/tofu60"
+ },
"eek": {
"target": "eek/silk_down"
},
@@ -212,6 +209,15 @@
"gmmk/pro/iso": {
"target": "gmmk/pro/rev1/iso"
},
+ "handwired/dactyl_manuform/3x5_3": {
+ "target": "handwired/dactyl_minidox"
+ },
+ "handwired/dactyl_manuform/6x6_kinesis": {
+ "target": "handwired/dactyl_kinesis"
+ },
+ "handwired/dactyl_manuform/dmote/62key": {
+ "target": "handwired/dmote"
+ },
"handwired/ferris": {
"target": "ferris/0_1"
},
@@ -221,6 +227,21 @@
"handwired/p1800fl": {
"target": "team0110/p1800fl"
},
+ "handwired/jscotto/scotto9": {
+ "target": "handwired/scottokeebs/scotto9"
+ },
+ "handwired/jscotto/scotto36": {
+ "target": "handwired/scottokeebs/scotto36"
+ },
+ "handwired/jscotto/scotto40": {
+ "target": "handwired/scottokeebs/scotto40"
+ },
+ "handwired/jscotto/scottocmd": {
+ "target": "handwired/scottokeebs/scottocmd"
+ },
+ "handwired/jscotto/scottostarter": {
+ "target": "handwired/scottokeebs/scottostarter"
+ },
"helix/pico/sc/back": {
"target": "helix/pico/sc"
},
@@ -264,13 +285,10 @@
"target": "keyhive/honeycomb"
},
"idb_60": {
- "target": "idb/idb_60",
- "layouts": {
- "LAYOUT": "LAYOUT_all"
- }
+ "target": "idb/idb_60"
},
"idobo": {
- "target": "idobao/id75"
+ "target": "idobao/id75/v1"
},
"jacky_studio/piggy60": {
"target": "jacky_studio/piggy60/rev1"
@@ -288,19 +306,13 @@
"target": "jones/v03_1"
},
"kamigakushi": {
- "target": "jaykeeb/kamigakushi",
- "layouts": {
- "LAYOUT": "LAYOUT_65_ansi_blocker_tsangan"
- }
+ "target": "jaykeeb/kamigakushi"
},
"katana60": {
"target": "rominronin/katana60/rev1"
},
"kbdfans/kbd67mkiirgb": {
- "target": "kbdfans/kbd67/mkiirgb",
- "layouts": {
- "LAYOUT": "LAYOUT_65_ansi_blocker"
- }
+ "target": "kbdfans/kbd67/mkiirgb"
},
"kbdfans/kbd67/mkiirgb": {
"target": "kbdfans/kbd67/mkiirgb/v1"
@@ -398,6 +410,9 @@
"maartenwut/wonderland": {
"target": "evyd13/wonderland"
},
+ "matchstickworks/southpad": {
+ "target": "matchstickworks/southpad/rev2/"
+ },
"matrix/m12og": {
"target": "matrix/m12og/rev1"
},
@@ -408,7 +423,7 @@
"target": "mechlovin/adelais/rgb_led/rev1"
},
"mechlovin/adelais/standard_led": {
- "target": "mechlovin/adelais/standard_led/rev2"
+ "target": "mechlovin/adelais/standard_led/arm/rev2"
},
"mechlovin/delphine": {
"target": "mechlovin/delphine/mono_led"
@@ -446,11 +461,6 @@
"mschwingen/modelm": {
"target": "ibm/model_m/mschwingen"
},
- "noxary/268_2": {
- "layouts": {
- "LAYOUT": "LAYOUT_65_ansi_blocker"
- }
- },
"oddball": {
"target": "oddball/v1"
},
@@ -467,24 +477,19 @@
"target": "pabile/p20/ver1"
},
"pancake/feather": {
- "target": "spaceman/pancake/feather"
+ "target": "spaceman/pancake/rev1/feather"
},
"pancake/promicro": {
- "target": "spaceman/pancake/promicro"
+ "target": "spaceman/pancake/rev1/promicro"
},
"peiorisboards/ixora": {
"target": "coarse/ixora"
},
- "percent/canoe": {
- "layouts": {
- "LAYOUT_iso": "LAYOUT_65_iso_blocker"
- }
- },
"plaid": {
"target": "dm9records/plaid"
},
"plain60": {
- "target": "maartenwut/plain60"
+ "target": "evyd13/plain60"
},
"ploopyco/trackball": {
"target": "ploopyco/trackball/rev1_005"
@@ -492,21 +497,6 @@
"polilla": {
"target": "polilla/rev1"
},
- "preonic/rev1": {
- "layouts": {
- "LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
- }
- },
- "preonic/rev2": {
- "layouts": {
- "LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
- }
- },
- "preonic/rev3": {
- "layouts": {
- "LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
- }
- },
"primekb/prime_l": {
"target": "primekb/prime_l/v1"
},
@@ -535,10 +525,10 @@
"target": "wilba_tech/rama_works_u80_a"
},
"ramonimbao/herringbone": {
- "target": "ramonimbao/herringbone/v1"
+ "target": "rmi_kb/herringbone/v1"
},
"ramonimbao/mona": {
- "target": "ramonimbao/mona/v1"
+ "target": "rmi_kb/mona/v1"
},
"rgbkb/pan": {
"target": "rgbkb/pan/rev1/32a"
@@ -574,10 +564,10 @@
"target": "tkw/stoutgat/v1"
},
"suihankey": {
- "target": "suihankey/split/alpha"
+ "target": "kakunpc/suihankey/split/alpha"
},
"ta65": {
- "target": "maartenwut/ta65"
+ "target": "evyd13/ta65"
},
"tartan": {
"target": "dm9records/tartan"
@@ -595,16 +585,13 @@
"target": "matthewdias/txuu"
},
"underscore33": {
- "target": "underscore33/rev1"
+ "target": "tominabox1/underscore33/rev1"
},
"vinta": {
- "target": "coarse/vinta",
- "layouts": {
- "LAYOUT_67_ansi": "LAYOUT_65_ansi_blocker"
- }
+ "target": "coarse/vinta"
},
"wasdat": {
- "target": "maartenwut/wasdat"
+ "target": "evyd13/wasdat"
},
"westfoxtrot/cypher": {
"target": "westfoxtrot/cypher/rev1"
@@ -616,10 +603,10 @@
"target": "xiudi/xd002"
},
"xd004": {
- "target": "xiudi/xd004"
+ "target": "xiudi/xd004/v1"
},
"xd60": {
- "target": "xiudi/xd60"
+ "target": "xiudi/xd60/rev2"
},
"xd68": {
"target": "xiudi/xd68"
@@ -866,19 +853,22 @@
"target": "kagizaraya/halberd"
},
"handwired/hillside/0_1": {
- "target": "handwired/hillside/48"
+ "target": "hillside/48/0_1"
},
"hecomi/alpha": {
"target": "takashiski/hecomi/alpha"
},
+ "hfdkb/keyboard_sw/k83":{
+ "target": "inland/kb83"
+ },
"hid_liber": {
"target": "bpiphany/hid_liber"
},
"id67/default_rgb": {
- "target": "idobao/id67/default_rgb"
+ "target": "idobao/id67"
},
"id67/rgb": {
- "target": "idobao/id67/rgb"
+ "target": "idobao/id67"
},
"id80": {
"target": "idobao/id80/v2/ansi"
@@ -916,6 +906,18 @@
"kelowna/rgb64": {
"target": "weirdo/kelowna/rgb64"
},
+ "keychron/q0": {
+ "target": "keychron/q0/base"
+ },
+ "keychron/q1": {
+ "target": "keychron/q1v1/ansi"
+ }
+ "keychron/q4": {
+ "target": "keychron/q4/ansi/v1"
+ }
+ "kprepublic/bm40hsrgb": {
+ "target": "kprepublic/bm40hsrgb/rev1"
+ },
"kprepublic/bm65hsrgb_iso": {
"target": "kprepublic/bm65hsrgb_iso/rev1"
},
@@ -1216,6 +1218,12 @@
"setta21": {
"target": "salicylic_acid3/setta21"
},
+ "soda/mango": {
+ "target": "magic_force/mf17"
+ },
+ "soda/pocket": {
+ "target": "magic_force/mf34"
+ },
"space_space/rev1": {
"target": "qpockets/space_space/rev1"
},
@@ -1240,6 +1248,9 @@
"stella": {
"target": "hnahkb/stella"
},
+ "studiokestra/line_tkl": {
+ "target": "studiokestra/line_friends_tkl"
+ },
"suihankey/alpha": {
"target": "kakunpc/suihankey/alpha"
},
@@ -1268,7 +1279,7 @@
"target": "marksard/treadstone48/rev2"
},
"tronguylabs/m122_3270": {
- "target": "ibm/model_m_122/m122_3270"
+ "target": "ibm/model_m_122/m122_3270/teensy"
},
"ua62": {
"target": "nacly/ua62"
@@ -1322,7 +1333,7 @@
"target": "ydkb/yd68"
},
"ymd75": {
- "target": "ymdk/ymd75"
+ "target": "ymdk/ymd75/rev1"
},
"ymd96": {
"target": "ymdk/ymd96"
@@ -1344,5 +1355,9 @@
},
"zinc/reva": {
"target": "25keys/zinc/reva"
+ },
+ // Moved during 2023 Q4 cycle
+ "ymdk/melody96": {
+ "target": "ymdk/melody96/soldered"
}
}
diff --git a/data/schemas/definitions.jsonschema b/data/schemas/definitions.jsonschema
index b9c64a55ec44..a1fdd2dcc680 100644
--- a/data/schemas/definitions.jsonschema
+++ b/data/schemas/definitions.jsonschema
@@ -3,10 +3,25 @@
"$id": "qmk.definitions.v1",
"title": "Common definitions used across QMK's jsonschemas.",
"type": "object",
+ "bcd_version": {
+ "type": "string",
+ "pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
+ },
+ "bit": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 1
+ },
"boolean_array": {
"type": "object",
"additionalProperties": {"type": "boolean"}
},
+ "build_target": {
+ "oneOf": [
+ {"$ref": "#/keyboard_keymap_tuple"},
+ {"$ref": "#/json_file_path"}
+ ]
+ },
"filename": {
"type": "string",
"minLength": 1,
@@ -20,14 +35,56 @@
"type": "string",
"pattern": "^0x[0-9A-F]{4}$"
},
- "bcd_version": {
+ "json_file_path": {
"type": "string",
- "pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
+ "pattern": "^[0-9a-z_/\\-]+\\.json$"
},
- "text_identifier": {
+ "key_unit": {
+ "type": "number"
+ },
+ "keyboard": {
"type": "string",
- "minLength": 1,
- "maxLength": 250
+ "pattern": "^[0-9a-z][0-9a-z_/]*$"
+ },
+ "keyboard_keymap_tuple": {
+ "type": "array",
+ "prefixItems": [
+ {"$ref": "#/keyboard"},
+ {"$ref": "#/filename"}
+ ],
+ "unevaluatedItems": false
+ },
+ "keycode": {
+ "type": "string",
+ "minLength": 2,
+ "maxLength": 50,
+ "pattern": "^[A-Z][A-Zs_0-9]*$"
+ },
+ "keycode_decl": {
+ "type": "object",
+ "required": [
+ "key"
+ ],
+ "properties": {
+ "key": {"$ref": "#/keycode"},
+ "label": {"$ref": "#/text_identifier"},
+ "aliases": {
+ "type": "array",
+ "minItems": 1,
+ "items": {"$ref": "#/keycode_short"}
+ }
+ }
+ },
+ "keycode_decl_array": {
+ "type": "array",
+ "minItems": 1,
+ "items": {"$ref": "#/keycode_decl"}
+ },
+ "keycode_short": {
+ "type": "string",
+ "minLength": 2,
+ "maxLength": 7,
+ "pattern": "^[A-Z][A-Zs_0-9]*$"
},
"layout_macro": {
"oneOf": [
@@ -64,49 +121,6 @@
}
]
},
- "key_unit": {
- "type": "number"
- },
- "keyboard": {
- "type": "string",
- "pattern": "^[0-9a-z][0-9a-z_/]*$"
- },
- "keycode": {
- "type": "string",
- "minLength": 2,
- "maxLength": 50,
- "pattern": "^[A-Z][A-Zs_0-9]*$"
- },
- "keycode_short": {
- "type": "string",
- "minLength": 2,
- "maxLength": 7,
- "pattern": "^[A-Z][A-Zs_0-9]*$"
- },
- "keycode_decl": {
- "type": "object",
- "required": [
- "key"
- ],
- "properties": {
- "key": {"$ref": "#/keycode"},
- "label": {"$ref": "#/text_identifier"},
- "aliases": {
- "type": "array",
- "minItems": 1,
- "items": {"$ref": "#/keycode_short"}
- }
- }
- },
- "keycode_decl_array": {
- "type": "array",
- "minItems": 1
- "items": {"$ref": "#/keycode_decl"}
- },
- "mcu_pin_array": {
- "type": "array",
- "items": {"$ref": "#/mcu_pin"}
- },
"mcu_pin": {
"oneOf": [
{
@@ -125,14 +139,14 @@
"type": "string",
"pattern": "^GP\\d{1,2}$"
},
- {
- "type": "integer"
- },
- {
- "type": "null"
- }
+ {"type": "integer"},
+ {"type": "null"}
]
},
+ "mcu_pin_array": {
+ "type": "array",
+ "items": {"$ref": "#/mcu_pin"}
+ },
"signed_decimal": {
"type": "number"
},
@@ -144,17 +158,22 @@
"minimum": -127,
"maximum": 127
},
+ "snake_case": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*$"
+ },
"string_array": {
"type": "array",
- "items": {
- "type": "string"
- }
+ "items": {"type": "string"}
},
"string_object": {
"type": "object",
- "additionalProperties": {
- "type": "string"
- }
+ "additionalProperties": {"type": "string"}
+ },
+ "text_identifier": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 250
},
"unsigned_decimal": {
"type": "number",
@@ -168,10 +187,5 @@
"type": "integer",
"minimum": 0,
"maximum": 255
- },
- "bit": {
- "type": "integer",
- "minimum": 0,
- "maximum": 1
}
}
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index ba4a7eec5570..299695808486 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -20,7 +20,15 @@
}
}
}
- }
+ },
+ "dip_switch_config": {
+ "type": "object",
+ "properties": {
+ "pins": {
+ "$ref": "qmk.definitions.v1#/mcu_pin_array"
+ }
+ }
+ },
},
"type": "object",
"not": { "required": [ "vendorId", "productId" ] }, // reject via keys...
@@ -71,6 +79,8 @@
"STM32F446",
"STM32G431",
"STM32G474",
+ "STM32H723",
+ "STM32H733",
"STM32L412",
"STM32L422",
"STM32L432",
@@ -126,6 +136,15 @@
"type": "string",
"enum": ["pwm", "software", "timer", "custom"]
},
+ "default": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "on": {"type": "boolean"},
+ "breathing": {"type": "boolean"},
+ "brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
+ }
+ },
"breathing": {"type": "boolean"},
"breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"levels": {
@@ -146,7 +165,7 @@
"properties": {
"driver": {
"type": "string",
- "enum": ["BluefruitLE", "RN42", "custom"]
+ "enum": ["bluefruit_le", "custom", "rn42"]
}
}
},
@@ -174,6 +193,7 @@
"bootloader": {
"type": "string",
"enum": [
+ "apm32-dfu",
"atmel-dfu",
"bootloadhid",
"caterina",
@@ -242,9 +262,40 @@
"type": "array",
"items": {"$ref": "qmk.definitions.v1#/filename"}
},
+ "dip_switch": {
+ "$ref": "#/definitions/dip_switch_config",
+ "properties": {
+ "enabled": {"type": "boolean"},
+ "matrix_grid": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "array",
+ "minItems": 2,
+ "maxItems": 2,
+ "items": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ }
+ }
+ },
"eeprom": {
"properties": {
- "driver": {"type": "string"}
+ "driver": {"type": "string"},
+ "wear_leveling": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "driver": {
+ "type": "string",
+ "enum": ["custom", "embedded_flash", "legacy", "rp2040_flash", "spi_flash"]
+ },
+ "backing_size": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "logical_size": {"$ref": "qmk.definitions.v1#/unsigned_int"}
+ }
+ }
}
},
"encoder": {
@@ -253,7 +304,11 @@
"enabled": {"type": "boolean"}
}
},
- "features": {"$ref": "qmk.definitions.v1#/boolean_array"},
+ "features": {
+ "$ref": "qmk.definitions.v1#/boolean_array",
+ "propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
+
+ },
"indicators": {
"type": "object",
"properties": {
@@ -293,6 +348,7 @@
"additionalProperties": false,
"required": ["x", "y"],
"properties": {
+ "encoder": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"label": {
"type": "string",
"pattern": "^[^\\n]*$"
@@ -367,10 +423,21 @@
"properties": {
"animations": {
"type": "object",
+ "propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": {
"type": "boolean"
}
},
+ "default": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "on": {"type": "boolean"},
+ "animation": {"type": "string"},
+ "val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
+ }
+ },
"driver": {"type": "string"},
"center_point": {
"type": "array",
@@ -380,10 +447,12 @@
},
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
- "hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
- "sat_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"speed_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "led_flush_limit": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "led_process_limit": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "react_on_keyup": {"type": "boolean"},
+ "sleep": {"type": "boolean"},
"split_count": {
"type": "array",
"minItems": 2,
@@ -418,10 +487,23 @@
"properties": {
"animations": {
"type": "object",
+ "propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": {
"type": "boolean"
}
},
+ "default": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "on": {"type": "boolean"},
+ "animation": {"type": "string"},
+ "hue": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "sat": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
+ }
+ },
"driver": {"type": "string"},
"center_point": {
"type": "array",
@@ -435,6 +517,10 @@
"sat_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"speed_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "led_flush_limit": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "led_process_limit": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "react_on_keyup": {"type": "boolean"},
+ "sleep": {"type": "boolean"},
"split_count": {
"type": "array",
"minItems": 2,
@@ -470,11 +556,28 @@
"properties": {
"animations": {
"type": "object",
+ "propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": {
"type": "boolean"
}
},
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "default": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "on": {"type": "boolean"},
+ "animation": {"type": "string"},
+ "hue": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "sat": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
+ }
+ },
+ "driver": {
+ "type": "string",
+ "enum": ["apa102", "custom", "ws2812"]
+ },
"hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"layers": {
"type": "object",
@@ -491,6 +594,11 @@
}
},
"led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "led_map": {
+ "type": "array",
+ "minItems": 2,
+ "items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
+ },
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"pin": {
"$ref": "qmk.definitions.v1#/mcu_pin",
@@ -576,10 +684,6 @@
}
}
},
- "matrix_grid": {
- "type": "array",
- "items": {"$ref": "qmk.definitions.v1#/mcu_pin"}
- },
"matrix_pins": {
"type": "object",
"additionalProperties": false,
@@ -599,6 +703,15 @@
}
}
},
+ "dip_switch": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "right": {
+ "$ref": "#/definitions/dip_switch_config"
+ }
+ }
+ },
"encoder": {
"type": "object",
"additionalProperties": false,
@@ -608,9 +721,17 @@
}
}
},
- "main": {
- "type": "string",
- "enum": ["eeprom", "left", "matrix_grid", "pin", "right"]
+ "handedness": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "matrix_grid": {
+ "$ref": "qmk.definitions.v1#/mcu_pin_array",
+ "minItems": 2,
+ "maxItems": 2
+ }
+ }
},
"soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"soft_serial_speed": {
@@ -626,10 +747,32 @@
"type": "string",
"enum": ["custom", "i2c", "serial", "serial_usart"]
},
- "sync_matrix_state": {"type": "boolean"},
- "sync_modifiers": {"type": "boolean"},
+ "sync": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "activity": {"type": "boolean"},
+ "detected_os": {"type": "boolean"},
+ "haptic": {"type": "boolean"},
+ "layer_state": {"type": "boolean"},
+ "indicators": {"type": "boolean"},
+ "matrix_state": {"type": "boolean"},
+ "modifiers": {"type": "boolean"},
+ "oled": {"type": "boolean"},
+ "st7565": {"type": "boolean"},
+ "wpm": {"type": "boolean"}
+ }
+ }
"watchdog": {"type": "boolean"},
- "watchdog_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
+ "watchdog_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "sync_matrix_state": {
+ "type": "boolean",
+ "$comment": "Deprecated: use sync.matrix_state instead"
+ },
+ "sync_modifiers": {
+ "type": "boolean",
+ "$comment": "Deprecated: use sync.modifiers instead"
+ }
}
},
"usb_detect": {
@@ -640,6 +783,16 @@
"polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
}
+ },
+ "main": {
+ "type": "string",
+ "enum": ["eeprom", "left", "matrix_grid", "pin", "right"],
+ "$comment": "Deprecated: use config.h options for now"
+ },
+ "matrix_grid": {
+ "type": "array",
+ "items": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "$comment": "Deprecated: use split.handedness.matrix_grid instead"
}
}
},
@@ -697,7 +850,15 @@
"properties": {
"keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
- "tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"}
+ "tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "locking": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled": {"type": "boolean"},
+ "resync": {"type": "boolean"}
+ }
+ }
}
},
"qmk_lufa_bootloader": {
diff --git a/data/schemas/user_repo_v0.jsonschema b/data/schemas/user_repo_v0.jsonschema
new file mode 100644
index 000000000000..b18ac504284b
--- /dev/null
+++ b/data/schemas/user_repo_v0.jsonschema
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema#",
+ "$id": "qmk.user_repo.v0",
+ "title": "User Repository Information",
+ "type": "object",
+ "required": [
+ "userspace_version"
+ ],
+ "properties": {
+ "userspace_version": {
+ "type": "string",
+ },
+ }
+}
diff --git a/data/schemas/user_repo_v1.jsonschema b/data/schemas/user_repo_v1.jsonschema
new file mode 100644
index 000000000000..6cdf758685c5
--- /dev/null
+++ b/data/schemas/user_repo_v1.jsonschema
@@ -0,0 +1,22 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema#",
+ "$id": "qmk.user_repo.v1",
+ "title": "User Repository Information",
+ "type": "object",
+ "required": [
+ "userspace_version",
+ "build_targets"
+ ],
+ "properties": {
+ "userspace_version": {
+ "type": "string",
+ "enum": ["1.0"]
+ },
+ "build_targets": {
+ "type": "array",
+ "items": {
+ "$ref": "qmk.definitions.v1#/build_target"
+ }
+ }
+ }
+}
diff --git a/docs/ChangeLog/20230827.md b/docs/ChangeLog/20230827.md
new file mode 100644
index 000000000000..12093d889f3f
--- /dev/null
+++ b/docs/ChangeLog/20230827.md
@@ -0,0 +1,305 @@
+# QMK Breaking Changes - 2023 Aug 27 Changelog
+
+## Notable Changes :id=notable-changes
+
+As per last few breaking changes cycles, there have been _a lot_ of behind-the-scenes changes, mainly around migration of configurables into `info.json` files, cleanup of `info.json` files, additional layout definitions for keyboards, adding support for general community layouts to keyboards, as well as addressing technical debt.
+
+One thing to note for this release -- `qmk/qmk_firmware` is no longer accepting PRs for keymaps other than for manufacturer-supported keymaps. User keymap workflow has been documented [here](https://docs.qmk.fm/#/newbs) for several years. This change is to progressively reduce the maintenance burden on the project, and to allow us to focus on the core features of QMK.
+
+Existing user keymaps and userspace areas will likely be relocated/removed in the future -- non-building keymaps and userspace will be first targets, likely during the new breaking changes cycle. We will provide more information on Discord regarding this initiative as it becomes available.
+
+### RGB Matrix optimizations ([#21134](https://github.com/qmk/qmk_firmware/pull/21134), [#21135](https://github.com/qmk/qmk_firmware/pull/21135)) :id=rgb-matrix-optimizations
+
+Most RGB Matrix implementations now check whether or not RGB LED data has changed and skip transmission if it hasn't. This was measured to improve scan frequency in cases of static or infrequently-changing colors.
+
+### Audio optimizations ([#21496](https://github.com/qmk/qmk_firmware/pull/21496), [#21498](https://github.com/qmk/qmk_firmware/pull/21498))
+
+Some audio code relating to "notes" used `double` datatypes, which are implemented in software floating-point for most ARM microcontrollers. This has been changed to use `float` datatypes instead, which are implemented in hardware floating-point on most ARM microcontrollers. This change increases performance as well as reduces the firmware size by significant number of bytes.
+
+AVR sees minimal (if any) benefit -- `double` was interpreted as `float` on AVR anyway.
+
+## Changes Requiring User Action :id=changes-requiring-user-action
+
+### Updated Keyboard Codebases :id=updated-keyboard-codebases
+
+| Old Keyboard Name | New Keyboard Name |
+|---------------------------------------|-------------------------------------|
+| capsunlocked/cu80/v2_ansi/base | capsunlocked/cu80/v2/ansi |
+| capsunlocked/cu80/v2_iso/base | capsunlocked/cu80/v2/iso |
+| handwired/dactyl_manuform/3x5_3 | handwired/dactyl_minidox |
+| handwired/dactyl_manuform/6x6_kinesis | handwired/dactyl_kinesis |
+| handwired/jscotto/scotto36 | handwired/scottokeebs/scotto36 |
+| handwired/jscotto/scotto40 | handwired/scottokeebs/scotto40 |
+| handwired/jscotto/scotto9 | handwired/scottokeebs/scotto9 |
+| handwired/jscotto/scottocmd | handwired/scottokeebs/scottocmd |
+| handwired/jscotto/scottostarter | handwired/scottokeebs/scottostarter |
+| hfdkb/keyboard_sw/k83 | inland/kb83 |
+| idb_60 | idb/idb_60 |
+| kamigakushi | jaykeeb/kamigakushi |
+| kbdfans/kbd67mkiirgb | kbdfans/kbd67/mkiirgb |
+| modelh | ibm/model_m/modelh |
+| vinta | coarse/vinta |
+
+### Remove encoder in-matrix workaround code ([#20389](https://github.com/qmk/qmk_firmware/pull/20389)) :id=remove-encoder-in-matrix-workaround-code
+
+Some keyboards "hacked" encoder support into spare slots in the key matrix in order to interoperate with VIA. This workaround is no longer necessary, and the code has been removed. If you have a keyboard that uses this workaround, you will need to update your keymap to use the new [Encoder Map](feature_encoders.md#encoder-map) API instead.
+
+### Unicodemap keycodes rename ([#21092](https://github.com/qmk/qmk_firmware/pull/21092)) :id=unicodemap-keycodes-rename
+
+The Unicodemap keycodes have been renamed:
+
+| Old | New |
+|-----------|-----------|
+| `X(i)` | `UM(i)` |
+| `XP(i,j)` | `UP(i,j)` |
+
+### Remove old OLED API code ([#21651](https://github.com/qmk/qmk_firmware/pull/21651)) :id=remove-old-oled-api-code
+
+Old OLED code using `ssd1306.c` `ssd1306.h`, and `SSD1306OLED` and other similar files have been consolidated to use the standard OLED driver. External user keymaps will need to be updated to use the standard OLED driver accordingly.
+
+### Driver naming consolidation ([#21551](https://github.com/qmk/qmk_firmware/pull/21551), [#21558](https://github.com/qmk/qmk_firmware/pull/21558), [#21580](https://github.com/qmk/qmk_firmware/pull/21580), [#21594](https://github.com/qmk/qmk_firmware/pull/21594), [#21624](https://github.com/qmk/qmk_firmware/pull/21624), [#21710](https://github.com/qmk/qmk_firmware/pull/21710)) :id=driver-naming-consolidation
+
+In most circumstances this won't affect users -- only keyboard designers with currently-unmerged boards. The only users affected are people who have modified existing keyboards in order to add/modify haptics, lighting, or bluetooth -- and only if the base keyboard did not configure them already. Driver naming has been modified to be lowercase.
+
+RGBLight (`RGBLIGHT_DRIVER` / `rgblight.driver`):
+
+| Old | New |
+|--------|--------|
+| `WS2812` | `ws2812` |
+| `APA102` | `apa102` |
+
+LED Matrix (`LED_MATRIX_DRIVER` / `led_matrix.driver`):
+
+| Old | New |
+|-------------|-------------|
+| `IS31FL3731` | `is31fl3731` |
+| `IS31FL3742A` | `is31fl3742a` |
+| `IS31FL3743A` | `is31fl3743a` |
+| `IS31FL3745` | `is31fl3745` |
+| `IS31FL3746A` | `is31fl3746a` |
+| `CKLED2001` | `ckled2001` |
+
+RGB Matrix (`RGB_MATRIX_DRIVER` / `rgb_matrix.driver`):
+
+| Old | New |
+|-------------|-------------|
+| `AW20216` | `aw20216` |
+| `IS31FL3731` | `is31fl3731` |
+| `IS31FL3733` | `is31fl3733` |
+| `IS31FL3736` | `is31fl3736` |
+| `IS31FL3737` | `is31fl3737` |
+| `IS31FL3741` | `is31fl3741` |
+| `IS31FL3742A` | `is31fl3742a` |
+| `IS31FL3743A` | `is31fl3743a` |
+| `IS31FL3745` | `is31fl3745` |
+| `IS31FL3746A` | `is31fl3746a` |
+| `CKLED2001` | `ckled2001` |
+| `WS2812` | `ws2812` |
+
+OLED (`OLED_DRIVER`):
+
+| Old | New |
+|---------|---------|
+| `SSD1306` | `ssd1306` |
+
+Haptic (`HAPTIC_DRIVER`):
+
+| Old | New |
+|----------|----------|
+| `DRV2605L` | `drv2605l` |
+| `SOLENOID` | `solenoid` |
+
+Bluetooth (`BLUETOOTH_DRIVER` / `bluetooth.driver`):
+
+| Old | New |
+|-------------|--------------|
+| `BluefruitLE` | `bluefruit_le` |
+| `RN42` | `rn42` |
+
+## Full changelist :id=full-changelist
+
+Core:
+* On-each-release tap dance function ([#20255](https://github.com/qmk/qmk_firmware/pull/20255))
+* Send a dummy keycode to neutralize flashing modifiers in retro tap and key overrides ([#20992](https://github.com/qmk/qmk_firmware/pull/20992))
+* Adds a way to separate tab from AUTO_SHIFT_SPECIAL. ([#20996](https://github.com/qmk/qmk_firmware/pull/20996))
+* [Enhancement] More info on `apply_autocorrect` ([#21056](https://github.com/qmk/qmk_firmware/pull/21056))
+* Remove quantum/keymap.h ([#21086](https://github.com/qmk/qmk_firmware/pull/21086))
+* Unicodemap keycodes rename ([#21092](https://github.com/qmk/qmk_firmware/pull/21092))
+* Merge upstream uf2conv.py changes ([#21107](https://github.com/qmk/qmk_firmware/pull/21107))
+* Add a dynamic_macro_stop_recording(void) function. ([#21108](https://github.com/qmk/qmk_firmware/pull/21108))
+* platforms: chibios: wait: only define the frequency ([#21115](https://github.com/qmk/qmk_firmware/pull/21115))
+* [Enhancement] Decouple autocorrect logic ([#21116](https://github.com/qmk/qmk_firmware/pull/21116))
+* Optimisation - Add RGB LED colour set check in drivers ([#21134](https://github.com/qmk/qmk_firmware/pull/21134))
+* RGB matrix ws2812 update ([#21135](https://github.com/qmk/qmk_firmware/pull/21135))
+* Pixel rain: Refactor the rain light decision operator ([#21139](https://github.com/qmk/qmk_firmware/pull/21139))
+* Use unsigned integer for kinetic speed ([#21151](https://github.com/qmk/qmk_firmware/pull/21151))
+* Reset `matrix_need_update` properly in eager debouncing algorithms ([#21154](https://github.com/qmk/qmk_firmware/pull/21154))
+* Refactor kinetic mouse key feature ([#21164](https://github.com/qmk/qmk_firmware/pull/21164))
+* RGB Matrix limit basic indicators to the last render ([#21169](https://github.com/qmk/qmk_firmware/pull/21169))
+* dynamic keymap: Rely on introspection to handle OOB access. ([#21247](https://github.com/qmk/qmk_firmware/pull/21247))
+* add VIA support for LED Matrix ([#21281](https://github.com/qmk/qmk_firmware/pull/21281))
+* Refactor times inverse of sqrt 2 calculation ([#21293](https://github.com/qmk/qmk_firmware/pull/21293))
+* Move protocol makefiles into their respective folders ([#21332](https://github.com/qmk/qmk_firmware/pull/21332))
+* Remove use of __flash within LED drivers ([#21343](https://github.com/qmk/qmk_firmware/pull/21343))
+* STM32H723 support ([#21352](https://github.com/qmk/qmk_firmware/pull/21352))
+* Remove CORTEX_ENABLE_WFI_IDLE from keyboards. ([#21353](https://github.com/qmk/qmk_firmware/pull/21353))
+* Get rid of `USB_LED_KANA` and `USB_LED_COMPOSE` ([#21366](https://github.com/qmk/qmk_firmware/pull/21366))
+* Minor board clean-up after #19780 ([#21391](https://github.com/qmk/qmk_firmware/pull/21391))
+* Get rid of `USB_LED_SCROLL_LOCK` ([#21405](https://github.com/qmk/qmk_firmware/pull/21405))
+* Get rid of `USB_LED_NUM_LOCK` ([#21424](https://github.com/qmk/qmk_firmware/pull/21424))
+* Simplify audio_duration_to_ms() and audio_ms_to_duration(), reduce firmware size by a few bytes. ([#21427](https://github.com/qmk/qmk_firmware/pull/21427))
+* Allow key override to respect weak mods caused by caps word ([#21434](https://github.com/qmk/qmk_firmware/pull/21434))
+* Get rid of `USB_LED_CAPS_LOCK` ([#21436](https://github.com/qmk/qmk_firmware/pull/21436))
+* tmk_core: remove direct `quantum.h` includes ([#21465](https://github.com/qmk/qmk_firmware/pull/21465))
+* bootmagic mods covering the case when swapped mods are pressed at the same time (#21320) ([#21472](https://github.com/qmk/qmk_firmware/pull/21472))
+* drivers: remove direct `quantum.h` includes ([#21473](https://github.com/qmk/qmk_firmware/pull/21473))
+* debounce: remove direct `quantum.h` includes ([#21480](https://github.com/qmk/qmk_firmware/pull/21480))
+* keymap_extras: remove direct `quantum.h` includes ([#21485](https://github.com/qmk/qmk_firmware/pull/21485))
+* process_keycode: remove direct `quantum.h` includes ([#21486](https://github.com/qmk/qmk_firmware/pull/21486))
+* Add MOUSEKEY_WHEEL_DELTA documentation ([#21493](https://github.com/qmk/qmk_firmware/pull/21493))
+* Reduce needless precision in audio note frequency calculation ([#21496](https://github.com/qmk/qmk_firmware/pull/21496))
+* Remove needless precision in additive DAC sample generation ([#21498](https://github.com/qmk/qmk_firmware/pull/21498))
+* quantum: remove direct `quantum.h` includes ([#21507](https://github.com/qmk/qmk_firmware/pull/21507))
+* process_combo: restore wait.h header ([#21514](https://github.com/qmk/qmk_firmware/pull/21514))
+* Eliminate `TMK_COMMON_*` in makefiles ([#21517](https://github.com/qmk/qmk_firmware/pull/21517))
+* backlight: split AVR PWM and timer drivers ([#21540](https://github.com/qmk/qmk_firmware/pull/21540))
+* haptic: naming cleanups ([#21551](https://github.com/qmk/qmk_firmware/pull/21551))
+* rgblight: driver selection cleanups ([#21558](https://github.com/qmk/qmk_firmware/pull/21558))
+* LED Matrix: driver naming cleanups ([#21580](https://github.com/qmk/qmk_firmware/pull/21580))
+* Unify MIDI note calculation with the audio feature (from #21496) ([#21588](https://github.com/qmk/qmk_firmware/pull/21588))
+* Allow the user to select a single tone for the additive DAC ([#21591](https://github.com/qmk/qmk_firmware/pull/21591))
+* RGB Matrix: driver naming cleanups ([#21594](https://github.com/qmk/qmk_firmware/pull/21594))
+* Raw HID: documentation improvements ([#21596](https://github.com/qmk/qmk_firmware/pull/21596))
+* Unicode: move keycode aliases to a separate header ([#21613](https://github.com/qmk/qmk_firmware/pull/21613))
+* Bluetooth: driver naming cleanups ([#21624](https://github.com/qmk/qmk_firmware/pull/21624))
+* Remove old OLED API code ([#21651](https://github.com/qmk/qmk_firmware/pull/21651))
+* haptic: further naming cleanups ([#21682](https://github.com/qmk/qmk_firmware/pull/21682))
+* Simplfy RGB/LED matrix effect logic ([#21703](https://github.com/qmk/qmk_firmware/pull/21703))
+* OLED: driver naming cleanups ([#21710](https://github.com/qmk/qmk_firmware/pull/21710))
+
+CLI:
+* Add *_MATRIX_LED_COUNT generation/validation ([#19515](https://github.com/qmk/qmk_firmware/pull/19515))
+* Revert "Add *_MATRIX_LED_COUNT generation/validation" ([#21109](https://github.com/qmk/qmk_firmware/pull/21109))
+* Add *_MATRIX_LED_COUNT generation ([#21110](https://github.com/qmk/qmk_firmware/pull/21110))
+* feat, docs: WB32 flashing ([#21217](https://github.com/qmk/qmk_firmware/pull/21217))
+* Improve error messages when layout key matrix row/col is OOB ([#21640](https://github.com/qmk/qmk_firmware/pull/21640))
+
+Submodule updates:
+* Update ChibiOS-Contrib ([#21553](https://github.com/qmk/qmk_firmware/pull/21553))
+
+Keyboards:
+* Add support for Rastersoft MiniTKL ([#20230](https://github.com/qmk/qmk_firmware/pull/20230))
+* Remove encoder in-matrix workaround code ([#20389](https://github.com/qmk/qmk_firmware/pull/20389))
+* Revamp `dactyl_manuform` readme.md ([#20395](https://github.com/qmk/qmk_firmware/pull/20395))
+* added hackpad keyboard ([#20402](https://github.com/qmk/qmk_firmware/pull/20402))
+* Add `handwired/dactyl_cc` keyboard ([#20517](https://github.com/qmk/qmk_firmware/pull/20517))
+* Add Mino Plus Hotswap ([#20534](https://github.com/qmk/qmk_firmware/pull/20534))
+* Move kb83 keyboard. ([#20761](https://github.com/qmk/qmk_firmware/pull/20761))
+* Rename `dactyl_manuform` variant `3x5_3` ([#21015](https://github.com/qmk/qmk_firmware/pull/21015))
+* Update `k34` layout to `split_3x5_2` ([#21046](https://github.com/qmk/qmk_firmware/pull/21046))
+* giabalanai keymaps: transpose added ([#21054](https://github.com/qmk/qmk_firmware/pull/21054))
+* Move `RGBLIGHT_SLEEP` to data driven ([#21072](https://github.com/qmk/qmk_firmware/pull/21072))
+* update layouts of `dactyl_manuform/4x5_5` ([#21094](https://github.com/qmk/qmk_firmware/pull/21094))
+* Move `RGBLIGHT_LED_MAP` to data driven ([#21095](https://github.com/qmk/qmk_firmware/pull/21095))
+* Move `RGBLED_SPLIT` to data driven ([#21113](https://github.com/qmk/qmk_firmware/pull/21113))
+* Update `dactyl_promicro` readme ([#21144](https://github.com/qmk/qmk_firmware/pull/21144))
+* Delete jscotto directory ([#21157](https://github.com/qmk/qmk_firmware/pull/21157))
+* correct and modernise `dactyl_manuform/6x7` variant ([#21176](https://github.com/qmk/qmk_firmware/pull/21176))
+* Move `RGBLIGHT_SPLIT` to data driven ([#21190](https://github.com/qmk/qmk_firmware/pull/21190))
+* Minor amendment to `bcat` userspace to prevent build failure ([#21205](https://github.com/qmk/qmk_firmware/pull/21205))
+* FJLabs Swordfish Layout Macro Refactor ([#21234](https://github.com/qmk/qmk_firmware/pull/21234))
+* Add skyloong/Dt40 keyboard ([#21237](https://github.com/qmk/qmk_firmware/pull/21237))
+* `dactyl_manuform/6x7` correction ([#21240](https://github.com/qmk/qmk_firmware/pull/21240))
+* Amend `ryanbaekr` boards by pin definitions ([#21248](https://github.com/qmk/qmk_firmware/pull/21248))
+* EC Pro X JIS Layout Touch-Up ([#21260](https://github.com/qmk/qmk_firmware/pull/21260))
+* Eason Aeroboard Refactor ([#21271](https://github.com/qmk/qmk_firmware/pull/21271))
+* Move `RGBLED_NUM` to data driven ([#21278](https://github.com/qmk/qmk_firmware/pull/21278))
+* Remove default `TAPPING_TERM` from keyboard config.h ([#21284](https://github.com/qmk/qmk_firmware/pull/21284))
+* Move `RGBLIGHT_HUE/SAT/VAL_STEP` to data driven ([#21292](https://github.com/qmk/qmk_firmware/pull/21292))
+* Move `TAPPING_TERM` to data driven ([#21296](https://github.com/qmk/qmk_firmware/pull/21296))
+* Modernize, correct, and uniform `dactyl_manuform` variant `5x6_68` ([#21299](https://github.com/qmk/qmk_firmware/pull/21299))
+* rename and modernise `dactyl_manuform/6x6_kinesis` ([#21302](https://github.com/qmk/qmk_firmware/pull/21302))
+* ProtoTypist PT-60 Refactor ([#21322](https://github.com/qmk/qmk_firmware/pull/21322))
+* ProtoTypist PT-80 Refactor ([#21325](https://github.com/qmk/qmk_firmware/pull/21325))
+* add jels60v2 support ([#21337](https://github.com/qmk/qmk_firmware/pull/21337))
+* Move `RGB_MATRIX_HUE/SAT/VAL/SPD_STEP` to data driven ([#21354](https://github.com/qmk/qmk_firmware/pull/21354))
+* Move `TAPPING_TOGGLE` to data driven ([#21360](https://github.com/qmk/qmk_firmware/pull/21360))
+* Move `TAP_CODE_DELAY` to data driven ([#21363](https://github.com/qmk/qmk_firmware/pull/21363))
+* gmmk/pro: Turn off RGB when suspended ([#21370](https://github.com/qmk/qmk_firmware/pull/21370))
+* Move miscellaneous defines to data driven ([#21382](https://github.com/qmk/qmk_firmware/pull/21382))
+* kyria: remove `LAYOUT_stack` ([#21384](https://github.com/qmk/qmk_firmware/pull/21384))
+* Reduce `keebio/bamfk1:via` firmware size ([#21432](https://github.com/qmk/qmk_firmware/pull/21432))
+* Refactor `capsunlocked/cu80/v2` ([#21454](https://github.com/qmk/qmk_firmware/pull/21454))
+* Mechlovin Zed65 rev1 Develop Touch-Up ([#21476](https://github.com/qmk/qmk_firmware/pull/21476))
+* Add PW88 keyboard ([#21482](https://github.com/qmk/qmk_firmware/pull/21482))
+* Prepare ymdk/ymd75 for rev4 ([#21484](https://github.com/qmk/qmk_firmware/pull/21484))
+* Move `DEBOUNCE_TYPE` to data driven ([#21489](https://github.com/qmk/qmk_firmware/pull/21489))
+* aleblazer/zodiark:via: Disable two RGB effects ([#21495](https://github.com/qmk/qmk_firmware/pull/21495))
+* Spruce up `dactyl_lightcycle` and `dactyl_maximus` layouts ([#21519](https://github.com/qmk/qmk_firmware/pull/21519))
+* Amend layout and matrix positions for `dactyl_cc` ([#21523](https://github.com/qmk/qmk_firmware/pull/21523))
+* moved model h controller under ibm/model_m ([#21526](https://github.com/qmk/qmk_firmware/pull/21526))
+* tominabox1/le_chiffre refactor pt 1 ([#21567](https://github.com/qmk/qmk_firmware/pull/21567))
+* Update ERA65 PCB ([#21592](https://github.com/qmk/qmk_firmware/pull/21592))
+* Update `usb.`* for dactyl_cc ([#21612](https://github.com/qmk/qmk_firmware/pull/21612))
+* Kintwin controller for kinesis keyboard, split layout ([#21614](https://github.com/qmk/qmk_firmware/pull/21614))
+* Add STM32f3 Discovery onekey ([#21625](https://github.com/qmk/qmk_firmware/pull/21625))
+* Automata02 Alisaie Develop Touch-Up ([#21630](https://github.com/qmk/qmk_firmware/pull/21630))
+* Move RGBLight animations to data driven ([#21635](https://github.com/qmk/qmk_firmware/pull/21635))
+* Refactoring entirely Caticorn PCB ([#21644](https://github.com/qmk/qmk_firmware/pull/21644))
+* AMJKeyboard AMJ84 Develop Touch-Up ([#21645](https://github.com/qmk/qmk_firmware/pull/21645))
+* Remove layout aliases from keyboard_aliases.hjson ([#21658](https://github.com/qmk/qmk_firmware/pull/21658))
+* kikoslab/kl90: Remove invalid config option ([#21708](https://github.com/qmk/qmk_firmware/pull/21708))
+* Remove more legacy config.h options ([#21709](https://github.com/qmk/qmk_firmware/pull/21709))
+* add willoucom/keypad ([#21714](https://github.com/qmk/qmk_firmware/pull/21714))
+* Tidy up encoder in matrix references ([#21718](https://github.com/qmk/qmk_firmware/pull/21718))
+* Add city42 ([#21727](https://github.com/qmk/qmk_firmware/pull/21727))
+* feat: add squigglybob splitkb kyria rev2 keymap ([#21751](https://github.com/qmk/qmk_firmware/pull/21751))
+* Align SENSE75 with recent Drop additions ([#21757](https://github.com/qmk/qmk_firmware/pull/21757))
+
+Keyboard fixes:
+* fix `scheikled` keymap for `dactyl_manuform/4x6` ([#21206](https://github.com/qmk/qmk_firmware/pull/21206))
+* Fixup `dekunukem/duckypad` ([#21298](https://github.com/qmk/qmk_firmware/pull/21298))
+* Fixup `nightly_boards/n40_o` ([#21307](https://github.com/qmk/qmk_firmware/pull/21307))
+* Fix `rate/pistachio_pro:via` ([#21339](https://github.com/qmk/qmk_firmware/pull/21339))
+* Fix encoder map declarations ([#21435](https://github.com/qmk/qmk_firmware/pull/21435))
+* jones/v1: fix layout offset and disable audio on via keymap ([#21468](https://github.com/qmk/qmk_firmware/pull/21468))
+* Fix backlight support for some boards ([#21554](https://github.com/qmk/qmk_firmware/pull/21554))
+* kinesis: remove stacked split layouts ([#21569](https://github.com/qmk/qmk_firmware/pull/21569))
+* Fix layout offsets for a handful of boards ([#21636](https://github.com/qmk/qmk_firmware/pull/21636))
+* doio/kb38: fix layout ([#21704](https://github.com/qmk/qmk_firmware/pull/21704))
+* Fix drop/shift/v2 compilation ([#21800](https://github.com/qmk/qmk_firmware/pull/21800))
+* Fix keyboards with old RGB driver names ([#21815](https://github.com/qmk/qmk_firmware/pull/21815))
+* Fix keyboards with old RGB driver names ([#21817](https://github.com/qmk/qmk_firmware/pull/21817))
+
+Others:
+* Rework info.json reference ([#21324](https://github.com/qmk/qmk_firmware/pull/21324))
+* Enable auto-merge of develop to riot ([#21389](https://github.com/qmk/qmk_firmware/pull/21389))
+
+Bugs:
+* Fix non-functional S3 wakeup / resume from suspense ([#19780](https://github.com/qmk/qmk_firmware/pull/19780))
+* [Bugfix] Check `NULL` pointers on QP ([#20481](https://github.com/qmk/qmk_firmware/pull/20481))
+* Fix PS2_MOUSE_INVERT_BUTTONS ([#20646](https://github.com/qmk/qmk_firmware/pull/20646))
+* Fix backlight sync on suspend_power_down for split keyboards ([#21079](https://github.com/qmk/qmk_firmware/pull/21079))
+* Consolidate `KEYBOARD_OUTPUT`+`KEYMAP_OUTPUT`=>`INTERMEDIATE_OUTPUT` ([#21272](https://github.com/qmk/qmk_firmware/pull/21272))
+* Chibios USB: Take into account if host wants remote wakeup or not ([#21287](https://github.com/qmk/qmk_firmware/pull/21287))
+* Fix anchor IDs for some API references ([#21345](https://github.com/qmk/qmk_firmware/pull/21345))
+* Pixel fractal: Set minimum middle column value ([#21365](https://github.com/qmk/qmk_firmware/pull/21365))
+* Fix ili9xxx inversion opcode entry ([#21422](https://github.com/qmk/qmk_firmware/pull/21422))
+* Relocate backlight drivers ([#21444](https://github.com/qmk/qmk_firmware/pull/21444))
+* Fixup STM32-DFU ([#21447](https://github.com/qmk/qmk_firmware/pull/21447))
+* keycode aliases: work around ChibiOS ch.h include guard ([#21497](https://github.com/qmk/qmk_firmware/pull/21497))
+* Fix compilation error when Split Watchdog enabled ([#21543](https://github.com/qmk/qmk_firmware/pull/21543))
+* Revert " Fix compilation error when Split Watchdog enabled" ([#21572](https://github.com/qmk/qmk_firmware/pull/21572))
+* quantum.h: clean up process_keycode includes ([#21579](https://github.com/qmk/qmk_firmware/pull/21579))
+* Fix stuck note with square wave in additive DAC ([#21589](https://github.com/qmk/qmk_firmware/pull/21589))
+* [Fix] USB HID tests compliance ([#21626](https://github.com/qmk/qmk_firmware/pull/21626))
+* Fix Dynamic Macro Compilation for avr-gcc 5.4.0 + Linux ([#21653](https://github.com/qmk/qmk_firmware/pull/21653))
+* Unicode, Unicodemap and UCIS refactor ([#21659](https://github.com/qmk/qmk_firmware/pull/21659))
+* Audio: Don't play the first note of zero-note melodies ([#21661](https://github.com/qmk/qmk_firmware/pull/21661))
+* Fix mouse-key spamming empty reports ([#21663](https://github.com/qmk/qmk_firmware/pull/21663))
+* Restore usb suspend wakeup delay ([#21676](https://github.com/qmk/qmk_firmware/pull/21676))
+* Fix compilation error for APA on ChibiOS ([#21773](https://github.com/qmk/qmk_firmware/pull/21773))
+* fix: restore rgb matrix indicators to jellybean_raindrops animation ([#21792](https://github.com/qmk/qmk_firmware/pull/21792))
+* Remove `led_matrix.hue_steps` and `led_matrix.sat_steps` from schema ([#21827](https://github.com/qmk/qmk_firmware/pull/21827))
+* Revert changes to ChibiOS Suspend Code ([#21830](https://github.com/qmk/qmk_firmware/pull/21830))
+* Add "apm32-dfu" in keyboard.jsonschema ([#21842](https://github.com/qmk/qmk_firmware/pull/21842))
diff --git a/docs/ChangeLog/20231126.md b/docs/ChangeLog/20231126.md
new file mode 100644
index 000000000000..61cff520c805
--- /dev/null
+++ b/docs/ChangeLog/20231126.md
@@ -0,0 +1,336 @@
+# QMK Breaking Changes - 2023 November 26 Changelog
+
+## Notable Features :id=notable-features
+
+As per last few breaking changes cycles, there have been _a lot_ of behind-the-scenes changes, mainly around consolidation of config into `info.json` files, cleanup of `info.json` files, cleaning up driver naming, as well as addressing technical debt.
+
+As a followup to last cycle's [notable changes](20230827.md#notable-changes), as `qmk/qmk_firmware` is no longer accepting PRs for keymaps we're pleased to announce that storing and building keymaps externally from the normal QMK Firmware repository is now possible. This is done through the new [External Userspace](newbs_external_userspace.md) feature, more details below!
+
+## Changes Requiring User Action :id=changes-requiring-user-action
+
+### Updated Keyboard Codebases :id=updated-keyboard-codebases
+
+| Old Keyboard Name | New Keyboard Name |
+|---------------------------------------|-------------------------------|
+| adm42 | adm42/rev4 |
+| dp3000 | dp3000/rev1 |
+| handwired/dactyl_manuform/dmote/62key | handwired/dmote |
+| keychron/q0/rev_0130 | keychron/q0/base |
+| keychron/q0/rev_0131 | keychron/q0/plus |
+| keychron/q1/ansi | keychron/q1v1/ansi |
+| keychron/q1/ansi_encoder | keychron/q1v1/ansi_encoder |
+| keychron/q1/iso | keychron/q1v1/iso |
+| keychron/q1/iso_encoder | keychron/q1v1/iso_encoder |
+| keychron/q4/ansi_v1 | keychron/q4/ansi |
+| kprepublic/bm40hsrgb | kprepublic/bm40hsrgb/rev1 |
+| matchstickworks/southpad | matchstickworks/southpad/rev2 |
+| soda/mango | magic_force/mf17 |
+| soda/pocket | magic_force/mf34 |
+| studiokestra/line_tkl | studiokestra/line_friends_tkl |
+| ymdk/melody96 | ymdk/melody96/soldered |
+
+## Notable core changes :id=notable-core
+
+### External Userspace ([#22222](https://github.com/qmk/qmk_firmware/pull/22222))
+
+As mentioned above, the new External Userspace feature allows for keymaps to be stored and built externally from the main QMK Firmware repository. This allows for keymaps to be stored separately -- usually in their own repository -- and for users to be able to maintain and build their keymaps without needing to fork the main QMK Firmware repository.
+
+See the [External Userspace documentation](newbs_external_userspace.md) for more details.
+
+A significant portion of user keymaps have already been removed from `qmk/qmk_firmware` and more will follow in coming weeks. You can still recover your keymap from the tag [user-keymaps-still-present](https://github.com/qmk/qmk_firmware/tree/user-keymaps-still-present) if required -- a perfect time to migrate to the new External Userspace!
+
+!> This feature is still in beta, and we're looking for feedback on it. Please try it out and let us know what you think -- a new `#help-userspace` channel has been set up on Discord.
+
+### Improve and Cleanup Shutdown callbacks ([#21060](https://github.com/qmk/qmk_firmware/pull/20160)) :id=improve-and-cleanup-shutdown-callbacks
+
+Shutdown callbacks at the keyboard level were never present, preventing safe shutdown sequencing for peripherals such as OLEDs, RGB LEDs, and other devices. This PR adds a new `shutdown_kb` function, as well as amending `shutdown_user`, allowing for safe shutdown of peripherals at both keyboard and keymap level.
+
+See the [Keyboard Shutdown/Reboot Code](custom_quantum_functions.md#keyboard-shutdown-reboot-code) documentation for more details.
+
+### OLED Force Flush ([#20953](https://github.com/qmk/qmk_firmware/pull/20953)) :id=oled-force-flush
+
+Along with the new `shutdown_kb` function, a new API `oled_render_dirty(bool)` function has been added. This allows OLED contents to be written deterministically when supplied with `true` -- that is, the OLED will be updated immediately, rather than waiting for the next OLED update cycle. This allows for OLEDs to show things such as "BOOTLOADER MODE" and the like if resetting to bootloader from QMK.
+
+### Switch statement helpers for keycode ranges ([#20059](https://github.com/qmk/qmk_firmware/pull/20059)) :id=switch-statement-helpers-for-keycode-ranges
+
+Predefined ranges usable within switch statements have been added for groups of similar keycodes, where people who wish to handle entire blocks at once can do so. This allows keymaps to be immune to changes in keycode values, and also allows for more efficient code generation.
+
+The ranges are as follows:
+
+| Name | Mapping |
+|-------------------------------------|------------------------------------------------------------------------|
+| `INTERNAL_KEYCODE_RANGE` | `KC_NO ... KC_TRANSPARENT` |
+| `BASIC_KEYCODE_RANGE` | `KC_A ... KC_EXSEL` |
+| `SYSTEM_KEYCODE_RANGE` | `KC_SYSTEM_POWER ... KC_SYSTEM_WAKE` |
+| `CONSUMER_KEYCODE_RANGE` | `KC_AUDIO_MUTE ... KC_LAUNCHPAD` |
+| `MOUSE_KEYCODE_RANGE` | `KC_MS_UP ... KC_MS_ACCEL2` |
+| `MODIFIER_KEYCODE_RANGE` | `KC_LEFT_CTRL ... KC_RIGHT_GUI` |
+| `SWAP_HANDS_KEYCODE_RANGE` | `QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT` |
+| `MAGIC_KEYCODE_RANGE` | `QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK` |
+| `MIDI_KEYCODE_RANGE` | `QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP` |
+| `SEQUENCER_KEYCODE_RANGE` | `QK_SEQUENCER_ON ... QK_SEQUENCER_STEPS_CLEAR` |
+| `JOYSTICK_KEYCODE_RANGE` | `QK_JOYSTICK_BUTTON_0 ... QK_JOYSTICK_BUTTON_31` |
+| `PROGRAMMABLE_BUTTON_KEYCODE_RANGE` | `QK_PROGRAMMABLE_BUTTON_1 ... QK_PROGRAMMABLE_BUTTON_32` |
+| `AUDIO_KEYCODE_RANGE` | `QK_AUDIO_ON ... QK_AUDIO_VOICE_PREVIOUS` |
+| `STENO_KEYCODE_RANGE` | `QK_STENO_BOLT ... QK_STENO_COMB_MAX` |
+| `MACRO_KEYCODE_RANGE` | `QK_MACRO_0 ... QK_MACRO_31` |
+| `BACKLIGHT_KEYCODE_RANGE` | `QK_BACKLIGHT_ON ... QK_BACKLIGHT_TOGGLE_BREATHING` |
+| `RGB_KEYCODE_RANGE` | `RGB_TOG ... RGB_MODE_TWINKLE` |
+| `QUANTUM_KEYCODE_RANGE` | `QK_BOOTLOADER ... QK_ALT_REPEAT_KEY` |
+| `KB_KEYCODE_RANGE` | `QK_KB_0 ... QK_KB_31` |
+| `USER_KEYCODE_RANGE` | `QK_USER_0 ... QK_USER_31` |
+
+Usage:
+
+```c
+ switch (keycode) {
+ case KC_A ... KC_EXSEL:
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
+ /* do stuff with basic and modifier keycodes */
+```
+
+Becomes:
+
+```c
+ switch (keycode) {
+ case BASIC_KEYCODE_RANGE:
+ case MODIFIER_KEYCODE_RANGE:
+ /* do stuff with basic and modifier keycodes */
+```
+
+### Quantum Painter OLED support ([#19997](https://github.com/qmk/qmk_firmware/pull/19997)) :id=quantum-painter-oled-support
+
+Quantum Painter has picked up support for SH1106 displays -- commonly seen as 128x64 OLEDs. Support for both I2C and SPI displays is available.
+
+If you're already using OLED through `OLED_DRIVER_ENABLE = yes` or equivalent in `info.json` and wish to use Quantum Painter instead, you'll need to disable the old OLED system, instead enabling Quantum Painter as well as enabling the appropriate SH1106 driver. See the [Quantum Painter driver documentation](quantum_painter.md#quantum-painter-drivers) for more details. The old OLED driver is still available, and keymaps do not require migrating to Quantum Painter if you don't want to do so.
+
+### RGB/LED lighting driver naming and cleanup ([#21890](https://github.com/qmk/qmk_firmware/pull/21890), [#21891](https://github.com/qmk/qmk_firmware/pull/21891), [#21892](https://github.com/qmk/qmk_firmware/pull/21892), [#21903](https://github.com/qmk/qmk_firmware/pull/21903), [#21904](https://github.com/qmk/qmk_firmware/pull/21904), [#21905](https://github.com/qmk/qmk_firmware/pull/21905), [#21918](https://github.com/qmk/qmk_firmware/pull/21918), [#21929](https://github.com/qmk/qmk_firmware/pull/21929), [#21938](https://github.com/qmk/qmk_firmware/pull/21938), [#22004](https://github.com/qmk/qmk_firmware/pull/22004), [#22008](https://github.com/qmk/qmk_firmware/pull/22008), [#22009](https://github.com/qmk/qmk_firmware/pull/22009), [#22071](https://github.com/qmk/qmk_firmware/pull/22071), [#22090](https://github.com/qmk/qmk_firmware/pull/22090), [#22099](https://github.com/qmk/qmk_firmware/pull/22099), [#22126](https://github.com/qmk/qmk_firmware/pull/22126), [#22133](https://github.com/qmk/qmk_firmware/pull/22133), [#22163](https://github.com/qmk/qmk_firmware/pull/22163), [#22200](https://github.com/qmk/qmk_firmware/pull/22200), [#22308](https://github.com/qmk/qmk_firmware/pull/22308), [#22309](https://github.com/qmk/qmk_firmware/pull/22309), [#22311](https://github.com/qmk/qmk_firmware/pull/22311), [#22325](https://github.com/qmk/qmk_firmware/pull/22325), [#22365](https://github.com/qmk/qmk_firmware/pull/22365), [#22379](https://github.com/qmk/qmk_firmware/pull/22379), [#22380](https://github.com/qmk/qmk_firmware/pull/22380), [#22381](https://github.com/qmk/qmk_firmware/pull/22381), [#22383](https://github.com/qmk/qmk_firmware/pull/22383), [#22436](https://github.com/qmk/qmk_firmware/pull/22436))
+
+As you can probably tell by the list of PRs just above, there has been a lot of cleanup and consolidation this cycle when it comes to RGB/LED lighting drivers. The number of changes is too large to list here, but the general theme has been focusing on consistency of naming, both of drivers themselves and their respective implementation and configuration. Most changes only affect keyboard designers -- if you find that your in-development keyboard is no longer building due to naming of defines changing, your best bet is to refer to another board already in the repository which has had the changes applied.
+
+### Peripheral subsystem enabling ([#22253](https://github.com/qmk/qmk_firmware/pull/22253), [#22448](https://github.com/qmk/qmk_firmware/pull/22448), [#22106](https://github.com/qmk/qmk_firmware/pull/22106)) :id=peripheral-subsystem-enabling
+
+When enabling peripherals such as I2C, SPI, or Analog/ADC, some required manual inclusion of source files in order to provide driver support, and in some cases, when multiple drivers were using the same underlying peripheral, files were being added to the build multiple times.
+
+Most systems requiring other peripherals now mark their respective dependencies as "required", allowing the build system to check whether peripherals are necessary before including them in the build rather than having each location enable them manually.
+
+For a concrete example, users or keyboard designers who previously added `SRC += analog.c` in order to allow for analog readings via an ADC now should specify `ANALOG_DRIVER_REQUIRED = yes` instead. The full list of added options is as follows:
+
+| New option | Old Equivalent |
+|--------------------------------|------------------------------------------------------------|
+| `ANALOG_DRIVER_REQUIRED = yes` | `SRC += analog.c` |
+| `APA102_DRIVER_REQUIRED = yes` | `SRC += apa102.c` |
+| `I2C_DRIVER_REQUIRED = yes` | `SRC += i2c_master.c` or `QUANTUM_LIB_SRC += i2c_master.c` |
+| `SPI_DRIVER_REQUIRED = yes` | `SRC += spi_master.c` or `QUANTUM_LIB_SRC += spi_master.c` |
+| `UART_DRIVER_REQUIRED = yes` | `SRC += uart.c` |
+| `WS2812_DRIVER_REQUIRED = yes` | `SRC += ws2812.c` |
+
+### NKRO on V-USB boards ([#22398](https://github.com/qmk/qmk_firmware/pull/22398)) :id=vusb-nkro
+
+NKRO is now available for ATmega32A and 328P-based keyboards (including PS2AVRGB/Bootmapper boards), thanks to some internal refactoring and cleanup. To enable it, the process is the same as always - add `NKRO_ENABLE = yes` to your `rules.mk`, then assign and press the `NK_TOGG` keycode to switch modes.
+
+## Full changelist :id=full-changelist
+
+Core:
+* Compilation warning if both `keymap.json` and `keymap.c` exist ([#19939](https://github.com/qmk/qmk_firmware/pull/19939))
+* [QP] Add support for OLED, variable framebuffer bpp ([#19997](https://github.com/qmk/qmk_firmware/pull/19997))
+* Generate switch statement helpers for keycode ranges ([#20059](https://github.com/qmk/qmk_firmware/pull/20059))
+* Chibios SPI driver: allow some SPI pins to be left unassigned ([#20315](https://github.com/qmk/qmk_firmware/pull/20315))
+* Take care of scroll divisor remainders for PS/2 drag scroll ([#20732](https://github.com/qmk/qmk_firmware/pull/20732))
+* Add `RGBLIGHT_DEFAULT_ON` macro configuration option ([#20857](https://github.com/qmk/qmk_firmware/pull/20857))
+* Allow force flush of oled display. ([#20953](https://github.com/qmk/qmk_firmware/pull/20953))
+* Improve and Cleanup Shutdown callbacks ([#21060](https://github.com/qmk/qmk_firmware/pull/21060))
+* [Enhancement] QP Getters ([#21171](https://github.com/qmk/qmk_firmware/pull/21171))
+* Russian typewriter keymap file for popular legacy layout. ([#21174](https://github.com/qmk/qmk_firmware/pull/21174))
+* Improve directional transition of overlapping mouse keys ([#21494](https://github.com/qmk/qmk_firmware/pull/21494))
+* Add full solenoid support on split keyboards ([#21583](https://github.com/qmk/qmk_firmware/pull/21583))
+* Reduce popping during audio initialization using the additive DAC ([#21642](https://github.com/qmk/qmk_firmware/pull/21642))
+* [Maintenance] USB HID control packet as struct ([#21688](https://github.com/qmk/qmk_firmware/pull/21688))
+* Bump mouse endpoint packet size to 16 bytes ([#21711](https://github.com/qmk/qmk_firmware/pull/21711))
+* Allow customizing PWM frequency ([#21717](https://github.com/qmk/qmk_firmware/pull/21717))
+* Add simpler method for relocating functions to RAM. ([#21804](https://github.com/qmk/qmk_firmware/pull/21804))
+* Clean up RGB LED type ([#21859](https://github.com/qmk/qmk_firmware/pull/21859))
+* is31fl3741: Allow changing config register ([#21861](https://github.com/qmk/qmk_firmware/pull/21861))
+* Add _DEFAULT_ON lighting configuration options ([#21865](https://github.com/qmk/qmk_firmware/pull/21865))
+* Modify split config is_keyboard_master/left checks. ([#21875](https://github.com/qmk/qmk_firmware/pull/21875))
+* Remove old `IS_LED_ON/OFF()` macros ([#21878](https://github.com/qmk/qmk_firmware/pull/21878))
+* ckled2001: driver naming cleanups ([#21890](https://github.com/qmk/qmk_firmware/pull/21890))
+* aw20216: driver naming cleanups ([#21891](https://github.com/qmk/qmk_firmware/pull/21891))
+* is31fl3218: driver naming cleanups ([#21892](https://github.com/qmk/qmk_firmware/pull/21892))
+* is31fl3736: driver naming cleanups ([#21903](https://github.com/qmk/qmk_firmware/pull/21903))
+* is31fl3737: driver naming cleanups ([#21904](https://github.com/qmk/qmk_firmware/pull/21904))
+* is31fl3733: driver naming cleanups ([#21905](https://github.com/qmk/qmk_firmware/pull/21905))
+* Enable RP2040 support for apa102 RGB LED driver ([#21908](https://github.com/qmk/qmk_firmware/pull/21908))
+* is31fl3731: driver naming cleanups ([#21918](https://github.com/qmk/qmk_firmware/pull/21918))
+* is31fl3741: driver naming cleanups ([#21929](https://github.com/qmk/qmk_firmware/pull/21929))
+* refactor: move default RGB/LED matrix #defines ([#21938](https://github.com/qmk/qmk_firmware/pull/21938))
+* Added flower blooming on RGB Matrix effect ([#21948](https://github.com/qmk/qmk_firmware/pull/21948))
+* Remove 'Firmware size check does not yet support' message ([#21977](https://github.com/qmk/qmk_firmware/pull/21977))
+* chibios: mark boot2 bootlader data readonly ([#21986](https://github.com/qmk/qmk_firmware/pull/21986))
+* Complete RGB Matrix support for IS31FL3218 ([#22004](https://github.com/qmk/qmk_firmware/pull/22004))
+* Default wear leveling logical size to half backing ([#22006](https://github.com/qmk/qmk_firmware/pull/22006))
+* chibios: disable RWX segment warning on newer GNU lds ([#22007](https://github.com/qmk/qmk_firmware/pull/22007))
+* Add and use I2C address defines for ISSI LED drivers ([#22008](https://github.com/qmk/qmk_firmware/pull/22008))
+* Add and use PWM frequency defines for ISSI LED drivers ([#22009](https://github.com/qmk/qmk_firmware/pull/22009))
+* directly use object files when linking ELF ([#22025](https://github.com/qmk/qmk_firmware/pull/22025))
+* Lvgl rate control ([#22049](https://github.com/qmk/qmk_firmware/pull/22049))
+* Rename CKLED2001 driver to SNLED27351 ([#22071](https://github.com/qmk/qmk_firmware/pull/22071))
+* Move `PACKED` define to util.h ([#22074](https://github.com/qmk/qmk_firmware/pull/22074))
+* Simplify more feature driver defines ([#22090](https://github.com/qmk/qmk_firmware/pull/22090))
+* Update ISSI LED types ([#22099](https://github.com/qmk/qmk_firmware/pull/22099))
+* Move velocikey to within rgblight ([#22123](https://github.com/qmk/qmk_firmware/pull/22123))
+* is31fl3218: Add LED Matrix support ([#22126](https://github.com/qmk/qmk_firmware/pull/22126))
+* Set default board files for uf2boot bootloader ([#22129](https://github.com/qmk/qmk_firmware/pull/22129))
+* is31fl3736: extract single-color API ([#22133](https://github.com/qmk/qmk_firmware/pull/22133))
+* is31fl3737/3741: add LED Matrix support ([#22163](https://github.com/qmk/qmk_firmware/pull/22163))
+* Rename `DRIVER_ADDR_n` defines ([#22200](https://github.com/qmk/qmk_firmware/pull/22200))
+* New RGB Animations - 4 "Starlight" Animation Variations ([#22212](https://github.com/qmk/qmk_firmware/pull/22212))
+* QMK Userspace ([#22222](https://github.com/qmk/qmk_firmware/pull/22222))
+* Dedupe I2C, SPI, UART driver inclusions ([#22253](https://github.com/qmk/qmk_firmware/pull/22253))
+* Add "AC Next Keyboard Layout Select" consumer usage entry (macOS Globe key) ([#22256](https://github.com/qmk/qmk_firmware/pull/22256))
+* Separate 6KRO and NKRO report structs ([#22267](https://github.com/qmk/qmk_firmware/pull/22267))
+* Azoteq IQS5xx support ([#22280](https://github.com/qmk/qmk_firmware/pull/22280))
+* Add `_flush()` functions to LED drivers ([#22308](https://github.com/qmk/qmk_firmware/pull/22308))
+* Add `_LED_COUNT` defines to LED drivers ([#22309](https://github.com/qmk/qmk_firmware/pull/22309))
+* Infer LED DRIVER_COUNT from configured addresses ([#22311](https://github.com/qmk/qmk_firmware/pull/22311))
+* Added gamma values for ST7735 displays ([#22313](https://github.com/qmk/qmk_firmware/pull/22313))
+* Consolidate some EEPROM Driver configuration ([#22321](https://github.com/qmk/qmk_firmware/pull/22321))
+* V-USB: Add generic `send_report()` function ([#22323](https://github.com/qmk/qmk_firmware/pull/22323))
+* V-USB: Implement `GET_PROTOCOL` and `SET_PROTOCOL` handling ([#22324](https://github.com/qmk/qmk_firmware/pull/22324))
+* RGB/LED matrix use limits size optimisation ([#22325](https://github.com/qmk/qmk_firmware/pull/22325))
+* Relocate LED driver init code ([#22365](https://github.com/qmk/qmk_firmware/pull/22365))
+* WT RGB cleanups ([#22379](https://github.com/qmk/qmk_firmware/pull/22379))
+* LED drivers: use `PACKED` define from util.h ([#22380](https://github.com/qmk/qmk_firmware/pull/22380))
+* LED drivers: clean up `SWx`/`CSy` pullup/down resistor config ([#22381](https://github.com/qmk/qmk_firmware/pull/22381))
+* LED drivers: add defines for PWM and LED control register counts ([#22383](https://github.com/qmk/qmk_firmware/pull/22383))
+* V-USB: implement NKRO ([#22398](https://github.com/qmk/qmk_firmware/pull/22398))
+* Allow generic_features to handle subdirectories ([#22400](https://github.com/qmk/qmk_firmware/pull/22400))
+* Migrate some common features to generic ([#22403](https://github.com/qmk/qmk_firmware/pull/22403))
+* Remove requirement for `keymap_steno.h` include in keymaps ([#22423](https://github.com/qmk/qmk_firmware/pull/22423))
+* LED drivers: register naming cleanups ([#22436](https://github.com/qmk/qmk_firmware/pull/22436))
+* Slight refactor of joystick axis type into typedef ([#22445](https://github.com/qmk/qmk_firmware/pull/22445))
+* Generalise analog SRC inclusion ([#22448](https://github.com/qmk/qmk_firmware/pull/22448))
+* Revert "chibios: disable RWX segment warning on newer GNU lds" ([#22469](https://github.com/qmk/qmk_firmware/pull/22469))
+* chibios: disable RWX segment warning on newer GNU lds ([#22471](https://github.com/qmk/qmk_firmware/pull/22471))
+
+CLI:
+* Implement data driven lighting defaults ([#21825](https://github.com/qmk/qmk_firmware/pull/21825))
+* Generate keymap.json config options more forcefully ([#21960](https://github.com/qmk/qmk_firmware/pull/21960))
+* Implement data driven dip switches ([#22017](https://github.com/qmk/qmk_firmware/pull/22017))
+* Improve argument handling of c2json ([#22170](https://github.com/qmk/qmk_firmware/pull/22170))
+* Support additional split sync items for info.json ([#22193](https://github.com/qmk/qmk_firmware/pull/22193))
+* CLI refactoring for common build target APIs ([#22221](https://github.com/qmk/qmk_firmware/pull/22221))
+* Add dd mapping for hardware based split handedness ([#22369](https://github.com/qmk/qmk_firmware/pull/22369))
+* CLI parallel search updates ([#22525](https://github.com/qmk/qmk_firmware/pull/22525))
+* Remove duplicates from search results ([#22528](https://github.com/qmk/qmk_firmware/pull/22528))
+
+Keyboards:
+* Add KPRepublic/BM40hsrgb rev2 ([#16689](https://github.com/qmk/qmk_firmware/pull/16689))
+* update to data driven - superseeds part of https://github.com/qmk/qmk… ([#20220](https://github.com/qmk/qmk_firmware/pull/20220))
+* Modernize `dactyl_manuform/dmote` keyboard ([#20427](https://github.com/qmk/qmk_firmware/pull/20427))
+* add Skyloong/GK61_V1 keyboard ([#21364](https://github.com/qmk/qmk_firmware/pull/21364))
+* [Refactor] Make changes to some pins ([#21380](https://github.com/qmk/qmk_firmware/pull/21380))
+* Add missing fullsize extended default layouts ([#21402](https://github.com/qmk/qmk_firmware/pull/21402))
+* Add Skyloong/Gk61 PRO keyboard ([#21450](https://github.com/qmk/qmk_firmware/pull/21450))
+* Added skyloong/Qk21 v1 Number Pad ([#21467](https://github.com/qmk/qmk_firmware/pull/21467))
+* matchstickworks/southpad - Move files to rev1, add rev2 ([#21574](https://github.com/qmk/qmk_firmware/pull/21574))
+* partially modernize `dactyl_minidox` ([#21576](https://github.com/qmk/qmk_firmware/pull/21576))
+* tominabox1/le_chiffre oled rework ([#21611](https://github.com/qmk/qmk_firmware/pull/21611))
+* Add Skyloong/Gk61_pro_48 keyboard ([#21654](https://github.com/qmk/qmk_firmware/pull/21654))
+* Adding support for new Waffling60 revision ([#21664](https://github.com/qmk/qmk_firmware/pull/21664))
+* Leeloo revision 2 updates. ([#21671](https://github.com/qmk/qmk_firmware/pull/21671))
+* rename og60 to tofu60 ([#21684](https://github.com/qmk/qmk_firmware/pull/21684))
+* add tofujr v2 keyboard ([#21740](https://github.com/qmk/qmk_firmware/pull/21740))
+* Rotary numpad ([#21744](https://github.com/qmk/qmk_firmware/pull/21744))
+* Update era/divine ([#21767](https://github.com/qmk/qmk_firmware/pull/21767))
+* 1UpKeyboards Pi60 Layout Additions ([#21874](https://github.com/qmk/qmk_firmware/pull/21874))
+* BIOI keyboards: use core UART driver ([#21879](https://github.com/qmk/qmk_firmware/pull/21879))
+* Resolve some "Layout should not contain name of keyboard" lint warnings ([#21898](https://github.com/qmk/qmk_firmware/pull/21898))
+* fc660c/fc980c: clean up actuation point adjustment code ([#21964](https://github.com/qmk/qmk_firmware/pull/21964))
+* Chromatonemini info json revised to support qmk 0.22.2 ([#21966](https://github.com/qmk/qmk_firmware/pull/21966))
+* Migrate spi_flash WEAR_LEVELING_DRIVER to info.json ([#21978](https://github.com/qmk/qmk_firmware/pull/21978))
+* Remove duplication of RP2040 EEPROM defaults ([#21979](https://github.com/qmk/qmk_firmware/pull/21979))
+* Remove duplication of STM32L432 EEPROM defaults ([#21981](https://github.com/qmk/qmk_firmware/pull/21981))
+* Migrate spi EEPROM_DRIVER to info.json ([#21991](https://github.com/qmk/qmk_firmware/pull/21991))
+* Update Keychron Q1v1 ([#21993](https://github.com/qmk/qmk_firmware/pull/21993))
+* Update Keychron Q2 ([#21994](https://github.com/qmk/qmk_firmware/pull/21994))
+* Update Keychron Q3 ([#21995](https://github.com/qmk/qmk_firmware/pull/21995))
+* Update Keychron Q4 ([#21996](https://github.com/qmk/qmk_firmware/pull/21996))
+* Migrate WEAR_LEVELING_*_SIZE to info.json ([#22010](https://github.com/qmk/qmk_firmware/pull/22010))
+* Remove duplication of EEPROM defaults ([#22011](https://github.com/qmk/qmk_firmware/pull/22011))
+* Migrate i2c EEPROM_DRIVER to info.json ([#22013](https://github.com/qmk/qmk_firmware/pull/22013))
+* Remove config.h which only set DYNAMIC_KEYMAP_LAYER_COUNT ([#22034](https://github.com/qmk/qmk_firmware/pull/22034))
+* Add community layout support to tofu60 ([#22041](https://github.com/qmk/qmk_firmware/pull/22041))
+* Update Keychron Q0 ([#22068](https://github.com/qmk/qmk_firmware/pull/22068))
+* Remove custom ISSI lighting code ([#22073](https://github.com/qmk/qmk_firmware/pull/22073))
+* add dp3000 rev2 featuring rgblight ([#22084](https://github.com/qmk/qmk_firmware/pull/22084))
+* Remove ALLOW_WARNINGS and PICO_INTRINSICS_ENABLED ([#22085](https://github.com/qmk/qmk_firmware/pull/22085))
+* Partially migrate `DYNAMIC_KEYMAP_LAYER_COUNT` ([#22087](https://github.com/qmk/qmk_firmware/pull/22087))
+* feat(eyeohdesigns/babyv): rgb matrix ([#22105](https://github.com/qmk/qmk_firmware/pull/22105))
+* input_club/infinity60: remove custom 3731 code, convert to LED Matrix ([#22117](https://github.com/qmk/qmk_firmware/pull/22117))
+* YMDK Melody96 Break-Up ([#22121](https://github.com/qmk/qmk_firmware/pull/22121))
+* Remove duplicated rgblight implementation from mxss ([#22122](https://github.com/qmk/qmk_firmware/pull/22122))
+* KC60 Layout Standardization and Cleanup ([#22125](https://github.com/qmk/qmk_firmware/pull/22125))
+* Convert adm42 to data driven ([#22144](https://github.com/qmk/qmk_firmware/pull/22144))
+* Update Drop keyboards for develop ([#22145](https://github.com/qmk/qmk_firmware/pull/22145))
+* move soda/mango and soda/pocket to magic_force/mf17 and magic_force/mf34 ([#22151](https://github.com/qmk/qmk_firmware/pull/22151))
+* GMMK2 65% ISO Community Layout Support ([#22152](https://github.com/qmk/qmk_firmware/pull/22152))
+* Leeloo v2.1 revision 3 updates. ([#22236](https://github.com/qmk/qmk_firmware/pull/22236))
+* jian/rev1: convert to DIP Switch ([#22248](https://github.com/qmk/qmk_firmware/pull/22248))
+* Enable linking of encoders to switch within layout macros ([#22264](https://github.com/qmk/qmk_firmware/pull/22264))
+* Migrate recently introduced sync items ([#22305](https://github.com/qmk/qmk_firmware/pull/22305))
+* Rename LINE FRIENDS TKL keyboard ([#22310](https://github.com/qmk/qmk_firmware/pull/22310))
+* feat(mechwild/clunker): new layouts ([#22342](https://github.com/qmk/qmk_firmware/pull/22342))
+* Remove use of broken split.main ([#22363](https://github.com/qmk/qmk_firmware/pull/22363))
+* whitefox: remove pointless file ([#22366](https://github.com/qmk/qmk_firmware/pull/22366))
+* Migrate some EEPROM config to info.json ([#22434](https://github.com/qmk/qmk_firmware/pull/22434))
+* Remove unnecessary driver counts ([#22435](https://github.com/qmk/qmk_firmware/pull/22435))
+* Migrate some dip switch config to info.json ([#22437](https://github.com/qmk/qmk_firmware/pull/22437))
+* Remove userspace keymaps ([#22544](https://github.com/qmk/qmk_firmware/pull/22544))
+* Stub out community layout directory structure ([#22545](https://github.com/qmk/qmk_firmware/pull/22545))
+* Remove symbolic linked userspace folder ([#22548](https://github.com/qmk/qmk_firmware/pull/22548))
+
+Keyboard fixes:
+* fix unxmaal for 60_iso ([#21975](https://github.com/qmk/qmk_firmware/pull/21975))
+* Fix input_club/k_type when RGB Matrix disabled ([#22021](https://github.com/qmk/qmk_firmware/pull/22021))
+* Fixup snes_macropad on develop ([#22444](https://github.com/qmk/qmk_firmware/pull/22444))
+* Fix missed shutdown callbacks ([#22549](https://github.com/qmk/qmk_firmware/pull/22549))
+
+Others:
+* Implement data driven wear leveling ([#21906](https://github.com/qmk/qmk_firmware/pull/21906))
+* More data driven RGB/LED Matrix config ([#21939](https://github.com/qmk/qmk_firmware/pull/21939))
+* Update WS2812 docs and add APA102 docs ([#22106](https://github.com/qmk/qmk_firmware/pull/22106))
+* Add DD mappings for locking switch ([#22242](https://github.com/qmk/qmk_firmware/pull/22242))
+
+Bugs:
+* Improve test invocation, fix Retro Shift bugs, and add Auto+Retro Shift test cases ([#15889](https://github.com/qmk/qmk_firmware/pull/15889))
+* [Bugfix] `qp_ellipse` overflow ([#19005](https://github.com/qmk/qmk_firmware/pull/19005))
+* Cater for ECC failures in EFL wear-leveling. ([#19749](https://github.com/qmk/qmk_firmware/pull/19749))
+* Fix OSM on a OSL activated layer ([#20410](https://github.com/qmk/qmk_firmware/pull/20410))
+* Fixed WB32 MCU remote wakeup issue ([#20863](https://github.com/qmk/qmk_firmware/pull/20863))
+* Optimize the additive DAC code, fixing performance-related hangs ([#21662](https://github.com/qmk/qmk_firmware/pull/21662))
+* [Enhancement] Improvements for debounce test coverage + bug fixes for sym_defer_g and sym_eager_pr ([#21667](https://github.com/qmk/qmk_firmware/pull/21667))
+* fix: make clicky delay silent ([#21866](https://github.com/qmk/qmk_firmware/pull/21866))
+* Add `mousekey.h` include to `quantum.h` ([#21897](https://github.com/qmk/qmk_firmware/pull/21897))
+* Fix default layer value in eeconfig_init ([#21909](https://github.com/qmk/qmk_firmware/pull/21909))
+* Add RTC IRQ Priority to RP2040 board files ([#21926](https://github.com/qmk/qmk_firmware/pull/21926))
+* Update AW20216S LED type ([#22072](https://github.com/qmk/qmk_firmware/pull/22072))
+* LED/RGB Matrix: prefix driver defines ([#22088](https://github.com/qmk/qmk_firmware/pull/22088))
+* RGBLight/Backlight: add prefixed driver defines ([#22089](https://github.com/qmk/qmk_firmware/pull/22089))
+* Fix lower cpi bound on PMW33XX ([#22108](https://github.com/qmk/qmk_firmware/pull/22108))
+* Fix parsing/validation for 21939 ([#22148](https://github.com/qmk/qmk_firmware/pull/22148))
+* is31fl3733: complete LED Matrix support ([#22149](https://github.com/qmk/qmk_firmware/pull/22149))
+* Fix memory leak in realloc failure handling ([#22188](https://github.com/qmk/qmk_firmware/pull/22188))
+* avrdude: Version 7.2 changes the text output ([#22235](https://github.com/qmk/qmk_firmware/pull/22235))
+* Resolve invalid keyboard alias targets ([#22239](https://github.com/qmk/qmk_firmware/pull/22239))
+* Prep work for NKRO report separation ([#22268](https://github.com/qmk/qmk_firmware/pull/22268))
+* ChibiOS pin defs: use only vendor if present ([#22297](https://github.com/qmk/qmk_firmware/pull/22297))
+* Fix invalid LED driver config ([#22312](https://github.com/qmk/qmk_firmware/pull/22312))
+* Fix compilation error when led/rgb process limit is zero. ([#22328](https://github.com/qmk/qmk_firmware/pull/22328))
+* V-USB: Fix `GET_IDLE/SET_IDLE` ([#22332](https://github.com/qmk/qmk_firmware/pull/22332))
+* QP getters correction ([#22357](https://github.com/qmk/qmk_firmware/pull/22357))
+* Fix 'to_c' for config.h mappings ([#22364](https://github.com/qmk/qmk_firmware/pull/22364))
+* snled27351: fix missing `i2c_init()` ([#22446](https://github.com/qmk/qmk_firmware/pull/22446))
+* Move BACKLIGHT_PWM_PERIOD to correct docs section ([#22480](https://github.com/qmk/qmk_firmware/pull/22480))
+* `qmk find`: Fix failure with multiple filters ([#22497](https://github.com/qmk/qmk_firmware/pull/22497))
+* Fix `qmk find` failure due to circular imports ([#22523](https://github.com/qmk/qmk_firmware/pull/22523))
diff --git a/docs/_summary.md b/docs/_summary.md
index 8b7959c2b34f..bae93da5b6c2 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -4,7 +4,7 @@
* [Building Your First Firmware](newbs_building_firmware.md)
* [Flashing Firmware](newbs_flashing.md)
* [Getting Help/Support](support.md)
- * [Building With GitHub Userspace](newbs_building_firmware_workflow.md)
+ * [External Userspace](newbs_external_userspace.md)
* [Other Resources](newbs_learn_more_resources.md)
* [Syllabus](syllabus.md)
@@ -80,6 +80,7 @@
* [Caps Word](feature_caps_word.md)
* [Combos](feature_combo.md)
* [Debounce API](feature_debounce_type.md)
+ * [Digitizer](feature_digitizer.md)
* [EEPROM](feature_eeprom.md)
* [Key Lock](feature_key_lock.md)
* [Key Overrides](feature_key_overrides.md)
@@ -115,7 +116,6 @@
* [Bootmagic Lite](feature_bootmagic.md)
* [Converters](feature_converters.md)
* [Custom Matrix](custom_matrix.md)
- * [Digitizer](feature_digitizer.md)
* [DIP Switch](feature_dip_switch.md)
* [Encoders](feature_encoders.md)
* [Haptic Feedback](feature_haptic_feedback.md)
@@ -126,7 +126,6 @@
* [PS/2 Mouse](feature_ps2_mouse.md)
* [Split Keyboard](feature_split_keyboard.md)
* [Stenography](feature_stenography.md)
- * [Velocikey](feature_velocikey.md)
* Keyboard Building
* [Easy Maker for One Offs](easy_maker.md)
@@ -139,7 +138,7 @@
* Breaking Changes
* [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
- * [Most Recent ChangeLog](ChangeLog/20230528.md "QMK v0.21.0 - 2023 May 28")
+ * [Most Recent ChangeLog](ChangeLog/20231126.md "QMK v0.23.0 - 2023 Nov 26")
* [Past Breaking Changes](breaking_changes_history.md)
* C Development
@@ -148,6 +147,7 @@
* [Compatible Microcontrollers](compatible_microcontrollers.md)
* [Drivers](hardware_drivers.md)
* [ADC Driver](adc_driver.md)
+ * [APA102 Driver](apa102_driver.md)
* [Audio Driver](audio_driver.md)
* [I2C Driver](i2c_driver.md)
* [SPI Driver](spi_driver.md)
diff --git a/docs/adc_driver.md b/docs/adc_driver.md
index 494d90c94fa8..dd928e1e7f0a 100644
--- a/docs/adc_driver.md
+++ b/docs/adc_driver.md
@@ -9,7 +9,7 @@ This driver currently supports both AVR and a limited selection of ARM devices.
To use this driver, add the following to your `rules.mk`:
```make
-SRC += analog.c
+ANALOG_DRIVER_REQUIRED = yes
```
Then place this include at the top of your code:
diff --git a/docs/apa102_driver.md b/docs/apa102_driver.md
new file mode 100644
index 000000000000..1da2de6ca357
--- /dev/null
+++ b/docs/apa102_driver.md
@@ -0,0 +1,49 @@
+# APA102 Driver :id=apa102-driver
+
+This driver provides support for APA102 addressable RGB LEDs. They are similar to the [WS2812](ws2812_driver.md) LEDs, but have increased data and refresh rates.
+
+## Usage :id=usage
+
+In most cases, the APA102 driver code is automatically included if you are using either the [RGBLight](feature_rgblight.md) or [RGB Matrix](feature_rgb_matrix.md) feature with the `apa102` driver set, and you would use those APIs instead.
+
+However, if you need to use the driver standalone, add the following to your `rules.mk`:
+
+```make
+APA102_DRIVER_REQUIRED = yes
+```
+
+You can then call the APA102 API by including `apa102.h` in your code.
+
+## Basic Configuration :id=basic-configuration
+
+Add the following to your `config.h`:
+
+|Define |Default |Description |
+|---------------------------|-------------|------------------------------------------------------------------|
+|`APA102_DI_PIN` |*Not defined*|The GPIO pin connected to the DI pin of the first LED in the chain|
+|`APA102_CI_PIN` |*Not defined*|The GPIO pin connected to the CI pin of the first LED in the chain|
+|`APA102_DEFAULT_BRIGHTNESS`|`31` |The default global brightness level of the LEDs, from 0 to 31 |
+
+## API :id=api
+
+### `void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds)`
+
+Send RGB data to the APA102 LED chain.
+
+#### Arguments :id=api-apa102-setleds-arguments
+
+ - `rgb_led_t *start_led`
+ A pointer to the LED array.
+ - `uint16_t num_leds`
+ The length of the LED array.
+
+---
+
+### `void apa102_set_brightness(uint8_t brightness)`
+
+Set the global brightness.
+
+#### Arguments :id=api-apa102-set-brightness-arguments
+
+ - `uint8_t brightness`
+ The brightness level to set, from 0 to 31.
diff --git a/docs/breaking_changes.md b/docs/breaking_changes.md
index e660182c3286..70a9044c8c0e 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?
+* [2023 Nov 26](ChangeLog/20231126.md)
+* [2023 Aug 27](ChangeLog/20230827.md)
* [2023 May 28](ChangeLog/20230528.md)
-* [2023 Feb 26](ChangeLog/20230226.md)
-* [2022 Nov 26](ChangeLog/20221126.md)
* [Older Breaking Changes](breaking_changes_history.md)
## When is the next Breaking Change?
-The next Breaking Change is scheduled for August 27, 2023.
+The next Breaking Change is scheduled for November 26, 2023.
### Important Dates
-* 2023 May 28 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
-* 2023 Jul 30 - `develop` closed to new PRs.
-* 2023 Jul 30 - Call for testers.
-* 2023 Aug 13 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
-* 2023 Aug 20 - `develop` is locked, only critical bugfix PRs merged.
-* 2023 Aug 25 - `master` is locked, no PRs merged.
-* 2023 Aug 27 - Merge `develop` to `master`.
-* 2023 Aug 27 - `master` is unlocked. PRs can be merged again.
+* 2023 Nov 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
+* 2024 Jan 28 - `develop` closed to new PRs.
+* 2024 Jan 28 - Call for testers.
+* 2024 Feb 4 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
+* 2024 Feb 18 - `develop` is locked, only critical bugfix PRs merged.
+* 2024 Feb 22 - `master` is locked, no PRs merged.
+* 2024 Feb 25 - Merge `develop` to `master`.
+* 2024 Feb 25 - `master` is unlocked. PRs can be merged again.
## What changes will be included?
@@ -48,7 +48,7 @@ Criteria for acceptance:
Strongly suggested:
-* The PR has a ChangeLog file describing the changes under `/docs/Changelog/20230827`.
+* The PR has a ChangeLog file describing the changes under `/docs/Changelog/20240225`.
* This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PRs ID.
* One strong recommendation that the ChangeLog document matches the PR description on GitHub, so as to ensure traceability.
@@ -119,6 +119,7 @@ This happens immediately after the previous `develop` branch is merged to `maste
* `git commit -m 'Branch point for Breaking Change'`
* `git tag breakpoint___`
* `git push upstream breakpoint___`
+ * `git push upstream develop`
* All submodules under `lib` now need to be checked against their QMK-based forks:
* `git submodule foreach git log -n1`
diff --git a/docs/breaking_changes_history.md b/docs/breaking_changes_history.md
index 79f2899d2cf6..4ab890294bba 100644
--- a/docs/breaking_changes_history.md
+++ b/docs/breaking_changes_history.md
@@ -2,6 +2,8 @@
This page links to all previous changelogs from the QMK Breaking Changes process.
+* [2023 Nov 26](ChangeLog/20231126.md) - version 0.23.0
+* [2023 Aug 27](ChangeLog/20230827.md) - version 0.22.0
* [2023 May 28](ChangeLog/20230528.md) - version 0.21.0
* [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0
* [2022 Nov 26](ChangeLog/20221126.md) - version 0.19.0
diff --git a/docs/cli.md b/docs/cli.md
index 8684479d0c1d..0fa068dc7b0c 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -2,11 +2,11 @@
## Overview :id=overview
-The QMK CLI makes building and working with QMK keyboards easier. We have provided a number of commands to simplify and streamline tasks such as obtaining and compiling the QMK firmware, creating keymaps, and more.
+The QMK CLI (command line interface) makes building and working with QMK keyboards easier. We have provided a number of commands to simplify and streamline tasks such as obtaining and compiling the QMK firmware, creating keymaps, and more.
### Requirements :id=requirements
-QMK requires Python 3.6 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). These are installed automatically when you install the QMK CLI.
+QMK requires Python 3.7 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). These are installed automatically when you install the QMK CLI.
### Install Using Homebrew (macOS, some Linux) :id=install-using-homebrew
@@ -20,7 +20,7 @@ qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build
### Install Using pip :id=install-using-easy_install-or-pip
-If your system is not listed above you can install QMK manually. First ensure that you have Python 3.6 (or later) installed and have installed pip. Then install QMK with this command:
+If your system is not listed above you can install QMK manually. First ensure that you have Python 3.7 (or later) installed and have installed pip. Then install QMK with this command:
```
python3 -m pip install qmk
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index 79fd9de57576..cf174949afb1 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -362,6 +362,16 @@ This command is directory aware. It will automatically fill in KEYBOARD if you a
qmk list-keymaps -kb planck/ez
```
+## `qmk migrate`
+
+This command searches for legacy code that can be converted to the new `info.json` format and adds it to the specified keyboard's `info.json`.
+
+**Usage**:
+
+```
+qmk migrate [-h] -kb KEYBOARD [-f FILTER]
+```
+
## `qmk new-keyboard`
This command creates a new keyboard based on available templates.
@@ -482,6 +492,131 @@ $ qmk import-kbfirmware ~/Downloads/gh62.json
---
+# External Userspace Commands
+
+## `qmk userspace-add`
+
+This command adds a keyboard/keymap to the External Userspace build targets.
+
+**Usage**:
+
+```
+qmk userspace-add [-h] [-km KEYMAP] [-kb KEYBOARD] [builds ...]
+
+positional arguments:
+ builds List of builds in form :, or path to a keymap JSON file.
+
+options:
+ -h, --help show this help message and exit
+ -km KEYMAP, --keymap KEYMAP
+ The keymap to build a firmware for. Ignored when a configurator export is supplied.
+ -kb KEYBOARD, --keyboard KEYBOARD
+ The keyboard to build a firmware for. Ignored when a configurator export is supplied.
+```
+
+**Example**:
+
+```
+$ qmk userspace-add -kb planck/rev6 -km default
+Ψ Added planck/rev6:default to userspace build targets
+Ψ Saved userspace file to /home/you/qmk_userspace/qmk.json
+```
+
+## `qmk userspace-remove`
+
+This command removes a keyboard/keymap from the External Userspace build targets.
+
+**Usage**:
+
+```
+qmk userspace-remove [-h] [-km KEYMAP] [-kb KEYBOARD] [builds ...]
+
+positional arguments:
+ builds List of builds in form :, or path to a keymap JSON file.
+
+options:
+ -h, --help show this help message and exit
+ -km KEYMAP, --keymap KEYMAP
+ The keymap to build a firmware for. Ignored when a configurator export is supplied.
+ -kb KEYBOARD, --keyboard KEYBOARD
+ The keyboard to build a firmware for. Ignored when a configurator export is supplied.
+```
+
+**Example**:
+
+```
+$ qmk userspace-remove -kb planck/rev6 -km default
+Ψ Removed planck/rev6:default from userspace build targets
+Ψ Saved userspace file to /home/you/qmk_userspace/qmk.json
+```
+
+## `qmk userspace-list`
+
+This command lists the External Userspace build targets.
+
+**Usage**:
+
+```
+qmk userspace-list [-h] [-e]
+
+options:
+ -h, --help show this help message and exit
+ -e, --expand Expands any use of `all` for either keyboard or keymap.
+```
+
+**Example**:
+
+```
+$ qmk userspace-list
+Ψ Current userspace build targets:
+Ψ Keyboard: planck/rev6, keymap: you
+Ψ Keyboard: clueboard/66/rev3, keymap: you
+```
+
+## `qmk userspace-compile`
+
+This command compiles all the External Userspace build targets.
+
+**Usage**:
+
+```
+qmk userspace-compile [-h] [-e ENV] [-n] [-c] [-j PARALLEL] [-t]
+
+options:
+ -h, --help show this help message and exit
+ -e ENV, --env ENV Set a variable to be passed to make. May be passed multiple times.
+ -n, --dry-run Don't actually build, just show the commands to be run.
+ -c, --clean Remove object files before compiling.
+ -j PARALLEL, --parallel PARALLEL
+ Set the number of parallel make jobs; 0 means unlimited.
+ -t, --no-temp Remove temporary files during build.
+```
+
+**Example**:
+
+```
+$ qmk userspace-compile
+Ψ Preparing target list...
+Build planck/rev6:you [OK]
+Build clueboard/66/rev3:you [OK]
+```
+
+## `qmk userspace-doctor`
+
+This command examines your environment and alerts you to potential problems related to External Userspace.
+
+**Example**:
+
+```
+% qmk userspace-doctor
+Ψ QMK home: /home/you/qmk_userspace/qmk_firmware
+Ψ Testing userspace candidate: /home/you/qmk_userspace -- Valid `qmk.json`
+Ψ QMK userspace: /home/you/qmk_userspace
+Ψ Userspace enabled: True
+```
+
+---
+
# Developer Commands
## `qmk format-text`
diff --git a/docs/cli_development.md b/docs/cli_development.md
index d878deff17c4..8d4ee625352f 100644
--- a/docs/cli_development.md
+++ b/docs/cli_development.md
@@ -44,7 +44,7 @@ def hello(cli):
First we import the `cli` object from `milc`. This is how we interact with the user and control the script's behavior. We use `@cli.argument()` to define a command line flag, `--name`. This also creates a configuration variable named `hello.name` (and the corresponding `user.name`) which the user can set so they don't have to specify the argument. The `cli.subcommand()` decorator designates this function as a subcommand. The name of the subcommand will be taken from the name of the function.
-Once inside our function we find a typical "Hello, World!" program. We use `cli.log` to access the underlying [Logger Object](https://docs.python.org/3.6/library/logging.html#logger-objects), whose behavior is user controllable. We also access the value for name supplied by the user as `cli.config.hello.name`. The value for `cli.config.hello.name` will be determined by looking at the `--name` argument supplied by the user, if not provided it will use the value in the `qmk.ini` config file, and if neither of those is provided it will fall back to the default supplied in the `cli.argument()` decorator.
+Once inside our function we find a typical "Hello, World!" program. We use `cli.log` to access the underlying [Logger Object](https://docs.python.org/3.7/library/logging.html#logger-objects), whose behavior is user controllable. We also access the value for name supplied by the user as `cli.config.hello.name`. The value for `cli.config.hello.name` will be determined by looking at the `--name` argument supplied by the user, if not provided it will use the value in the `qmk.ini` config file, and if neither of those is provided it will fall back to the default supplied in the `cli.argument()` decorator.
# User Interaction
@@ -56,13 +56,13 @@ There are two main methods for outputting text in a subcommand- `cli.log` and `c
You can use special tokens to colorize your text, to make it easier to understand the output of your program. See [Colorizing Text](#colorizing-text) below.
-Both of these methods support built-in string formatting using python's [printf style string format operations](https://docs.python.org/3.6/library/stdtypes.html#old-string-formatting). You can use tokens such as `%s` and `%d` within your text strings then pass the values as arguments. See our Hello, World program above for an example.
+Both of these methods support built-in string formatting using python's [printf style string format operations](https://docs.python.org/3.7/library/stdtypes.html#old-string-formatting). You can use tokens such as `%s` and `%d` within your text strings then pass the values as arguments. See our Hello, World program above for an example.
You should never use the format operator (`%`) directly, always pass values as arguments.
### Logging (`cli.log`)
-The `cli.log` object gives you access to a [Logger Object](https://docs.python.org/3.6/library/logging.html#logger-objects). We have configured our log output to show the user a nice emoji for each log level (or the log level name if their terminal does not support unicode.) This way the user can tell at a glance which messages are most important when something goes wrong.
+The `cli.log` object gives you access to a [Logger Object](https://docs.python.org/3.7/library/logging.html#logger-objects). We have configured our log output to show the user a nice emoji for each log level (or the log level name if their terminal does not support unicode.) This way the user can tell at a glance which messages are most important when something goes wrong.
The default log level is `INFO`. If the user runs `qmk -v ` the default log level will be set to `DEBUG`.
diff --git a/docs/coding_conventions_python.md b/docs/coding_conventions_python.md
index 2b6870344873..1ed27ee46abb 100644
--- a/docs/coding_conventions_python.md
+++ b/docs/coding_conventions_python.md
@@ -317,7 +317,7 @@ At the time of this writing our tests are not very comprehensive. Looking at the
## Integration Tests
-Integration tests can be found in `lib/python/qmk/tests/test_cli_commands.py`. This is where CLI commands are actually run and their overall behavior is verified. We use [`subprocess`](https://docs.python.org/3.6/library/subprocess.html#module-subprocess) to launch each CLI command and a combination of checking output and returncode to determine if the right thing happened.
+Integration tests can be found in `lib/python/qmk/tests/test_cli_commands.py`. This is where CLI commands are actually run and their overall behavior is verified. We use [`subprocess`](https://docs.python.org/3.7/library/subprocess.html#module-subprocess) to launch each CLI command and a combination of checking output and returncode to determine if the right thing happened.
## Unit Tests
diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
index cc9c0b7f92a2..197033f78b57 100644
--- a/docs/compatible_microcontrollers.md
+++ b/docs/compatible_microcontrollers.md
@@ -43,6 +43,8 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
+ * [STM32H723](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
+ * [STM32H733](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
* [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L422](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L432](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
diff --git a/docs/config_options.md b/docs/config_options.md
index 4698260118f3..8119b9e356fa 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -439,7 +439,7 @@ Use these to enable or disable building certain features. The more you have enab
* `UNICODE_ENABLE`
* Unicode
* `BLUETOOTH_ENABLE`
- * Current options are BluefruitLE, RN42
+ * Current options are bluefruit_le, rn42
* `SPLIT_KEYBOARD`
* Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
* `CUSTOM_MATRIX`
diff --git a/docs/contributing.md b/docs/contributing.md
index 4801bb8224a4..8d993e3389d5 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -36,7 +36,7 @@ If you need help you can [open an issue](https://github.com/qmk/qmk_firmware/iss
Never made an open source contribution before? Wondering how contributions work in QMK? Here's a quick rundown!
0. Sign up for a [GitHub](https://github.com) account.
-1. Put together a keymap to contribute, [find an issue](https://github.com/qmk/qmk_firmware/issues) you are interested in addressing, or [a feature](https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) you would like to add.
+1. [Find an issue](https://github.com/qmk/qmk_firmware/issues) you are interested in addressing, or [a feature](https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) you would like to add.
2. Fork the repository associated with the issue to your GitHub account. This means that you will have a copy of the repository under `your-GitHub-username/qmk_firmware`.
3. Clone the repository to your local machine using `git clone https://github.com/github-username/repository-name.git`.
4. If you're working on a new feature consider opening an issue to talk with us about the work you're about to undertake.
@@ -67,9 +67,10 @@ We have a few different types of changes in QMK, each requiring a different leve
* Separate PRs into logical units. For example, do not submit one PR covering two separate features, instead submit a separate PR for each feature.
* Check for unnecessary whitespace with `git diff --check` before committing.
* Make sure your code change actually compiles.
- * Keymaps: Make sure that `make keyboard:your_new_keymap` does not return any errors.
+ * Keymaps: Make sure that `make keyboard:keymap` does not return any errors.
* Keyboards: Make sure that `make keyboard:all` does not return any errors.
* Core: Make sure that `make all` does not return any errors.
+* Note that user-keymap and userspace contributions are no longer accepted.
* Make sure commit messages are understandable on their own. You should put a short description (no more than 70 characters) on the first line, the second line should be empty, and on the 3rd and later lines you should describe your commit in detail, if required. Example:
```
@@ -80,8 +81,6 @@ The kerpleplork was intermittently failing with error code 23. The root cause wa
Limited experimentation on the devices I have available shows that 7 is high enough to avoid confusing the kerpleplork, but I'd like to get some feedback from people with ARM devices to be sure.
```
-!> **IMPORTANT:** If you would like to contribute a bugfix or improvement to user code, such as non-default keymaps, userspace and layouts, be sure to tag the original submitter of the code in your PR. Many users, regardless of skill level with Git and GitHub, may be confused or frustrated at their code being modified without their knowledge.
-
## Documentation
Documentation is one of the easiest ways to get started contributing to QMK. Finding places where the documentation is wrong or incomplete and fixing those is easy! We also very badly need someone to edit our documentation, so if you have editing skills but aren't sure where or how to jump in please [reach out for help](#where-can-i-go-for-help)!
@@ -114,16 +113,6 @@ or if you only have Python 3 installed:
and navigating to `http://localhost:8936/`.
-## Keymaps
-
-Most first-time QMK contributors start with their personal keymaps. We try to keep keymap standards pretty casual (keymaps, after all, reflect the personality of their creators) but we do ask that you follow these guidelines to make it easier for others to discover and learn from your keymap.
-
-* Write a `readme.md` using [the template](documentation_templates.md).
-* All Keymap PRs are squashed, so if you care about how your commits are squashed you should do it yourself
-* Do not lump features in with keymap PRs. Submit the feature first and then a second PR for the keymap.
-* Do not include `Makefile`s in your keymap folder (they're no longer used)
-* Update copyrights in file headers (look for `%YOUR_NAME%`)
-
## Keyboards
Keyboards are the raison d'être for QMK. Some keyboards are community maintained, while others are maintained by the people responsible for making a particular keyboard. The `readme.md` should tell you who maintains a particular keyboard. If you have questions relating to a particular keyboard you can [Open An Issue](https://github.com/qmk/qmk_firmware/issues) and tag the maintainer in your question.
@@ -131,7 +120,7 @@ Keyboards are the raison d'être for QMK. Some keyboards are community maintaine
We also ask that you follow these guidelines:
* Write a `readme.md` using [the template](documentation_templates.md).
-* Keep the number of commits reasonable or we will squash your PR
+* Include a `default` keymap that provides a clean slate for users to start with when creating their own keymaps.
* Do not lump core features in with new keyboards. Submit the feature first and then submit a separate PR for the keyboard.
* Name `.c`/`.h` file after the immediate parent folder, eg `/keyboards///.[ch]`
* Do not include `Makefile`s in your keyboard folder (they're no longer used)
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 5d63f3cfb7d0..957633837c42 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -283,6 +283,65 @@ void suspend_wakeup_init_user(void) {
* Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
* Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
+
+# Keyboard Shutdown/Reboot Code :id=keyboard-shutdown-reboot-code
+
+This function gets called whenever the firmware is reset, whether it's a soft reset or reset to the bootloader. This is the spot to use for any sort of cleanup, as this happens right before the actual reset. And it can be useful for turning off different systems (such as RGB, onboard screens, etc).
+
+Additionally, it differentiates between the soft reset (eg, rebooting back into the firmware) or jumping to the bootloader.
+
+Certain tasks are performed during shutdown too. The keyboard is cleared, music and midi is stopped (if enabled), the shutdown chime is triggered (if audio is enabled), and haptic is stopped.
+
+If `jump_to_bootloader` is set to `true`, this indicates that the board will be entering the bootloader for a new firmware flash, whereas `false` indicates that this is happening for a soft reset and will load the firmware agaim immediately (such as when using `QK_REBOOT` or `QK_CLEAR_EEPROM`).
+
+As there is a keyboard and user level function, returning `false` for the user function will disable the keyboard level function, allowing for customization.
+
+?> Bootmagic does not trigger `shutdown_*()` as it happens before most of the initialization process.
+
+### Example `shutdown_kb()` Implementation
+
+```c
+bool shutdown_kb(bool jump_to_bootloader) {
+ if (!shutdown_user(jump_to_bootloader)) {
+ return false;
+ }
+
+ if (jump_to_bootloader) {
+ // red for bootloader
+ rgb_matrix_set_color_all(RGB_OFF);
+ } else {
+ // off for soft reset
+ rgb_matrix_set_color_all(RGB_GREEN);
+ }
+ // force flushing -- otherwise will never happen
+ rgb_matrix_update_pwm_buffers();
+ return true;
+}
+```
+
+### Example `shutdown_user()` Implementation
+
+```c
+bool shutdown_user(bool jump_to_bootloader) {
+ if (jump_to_bootloader) {
+ // red for bootloader
+ rgb_matrix_set_color_all(RGB_RED);
+ } else {
+ // off for soft reset
+ rgb_matrix_set_color_all(RGB_OFF);
+ }
+ // force flushing -- otherwise will never happen
+ rgb_matrix_update_pwm_buffers();
+ // false to not process kb level
+ return false;
+}
+```
+
+### Keyboard shutdown/reboot Function Documentation
+
+* Keyboard/Revision: `bool shutdown_kb(bool jump_to_bootloader)`
+* Keymap: `bool shutdown_user(bool jump_to_bootloader)`
+
# Deferred Execution :id=deferred-execution
QMK has the ability to execute a callback after a specified period of time, rather than having to manually manage timers. To enable this functionality, set `DEFERRED_EXEC_ENABLE = yes` in rules.mk.
diff --git a/docs/data_driven_config.md b/docs/data_driven_config.md
index ba287f5688e9..b288f9901a81 100644
--- a/docs/data_driven_config.md
+++ b/docs/data_driven_config.md
@@ -79,8 +79,8 @@ If you are not sure how to edit this file or are not comfortable with Python [op
The final piece of the puzzle is providing your new option to the build system. This is done by generating two files:
-* `.build/obj_/src/info_config.h`
-* `.build/obj_/src/rules.mk`
+* `.build/obj__/src/info_config.h`
+* `.build/obj__/src/rules.mk`
These two files are generated by the code here:
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md
index 50d8bcb7b328..c77d18c68df5 100644
--- a/docs/eeprom_driver.md
+++ b/docs/eeprom_driver.md
@@ -66,6 +66,14 @@ Currently QMK supports 25xx-series chips over SPI. As such, requires a working s
`#define EXTERNAL_EEPROM_PAGE_SIZE` | `32` | Page size of the EEPROM in bytes, as specified in the datasheet
`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | `2` | The number of bytes to transmit for the memory location within the EEPROM
+Default values and extended descriptions can be found in `drivers/eeprom/eeprom_spi.h`.
+
+Alternatively, there are pre-defined hardware configurations for available chips/modules:
+
+Module | Equivalent `#define` | Source
+-----------------|---------------------------------|------------------------------------------
+MB85RS64V FRAM | `define EEPROM_SPI_MB85RS64V` |
+
!> There's no way to determine if there is an SPI EEPROM actually responding. Generally, this will result in reads of nothing but zero.
## Transient Driver configuration :id=transient-eeprom-driver-configuration
@@ -105,11 +113,11 @@ Configurable options in your keyboard's `config.h`:
`config.h` override | Default | Description
-----------------------------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-`#define WEAR_LEVELING_EFL_FIRST_SECTOR` | _unset_ | The first sector on the MCU to use. By default this is not defined and calculated at runtime based on the MCU. However, different flash sizes on MCUs may require custom configuration.
-`#define WEAR_LEVELING_EFL_FLASH_SIZE` | _unset_ | Allows overriding the flash size available for use for wear-leveling. Under normal circumstances this is automatically calculated and should not need to be overridden. Specifying a size larger than the amount actually available in flash will usually prevent the MCU from booting.
-`#define WEAR_LEVELING_LOGICAL_SIZE` | `1024` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
-`#define WEAR_LEVELING_BACKING_SIZE` | `2048` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size.
-`#define BACKING_STORE_WRITE_SIZE` | _automatic_ | The byte width of the underlying write used on the MCU, and is usually automatically determined from the selected MCU family. If an error occurs in the auto-detection, you'll need to consult the MCU's datasheet and determine this value, specifying it directly.
+`#define WEAR_LEVELING_EFL_FIRST_SECTOR` | _unset_ | The first sector on the MCU to use. By default this is not defined and calculated at runtime based on the MCU. However, different flash sizes on MCUs may require custom configuration.
+`#define WEAR_LEVELING_EFL_FLASH_SIZE` | _unset_ | Allows overriding the flash size available for use for wear-leveling. Under normal circumstances this is automatically calculated and should not need to be overridden. Specifying a size larger than the amount actually available in flash will usually prevent the MCU from booting.
+`#define WEAR_LEVELING_LOGICAL_SIZE` | `(backing_size/2)` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
+`#define WEAR_LEVELING_BACKING_SIZE` | `2048` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size.
+`#define BACKING_STORE_WRITE_SIZE` | _automatic_ | The byte width of the underlying write used on the MCU, and is usually automatically determined from the selected MCU family. If an error occurs in the auto-detection, you'll need to consult the MCU's datasheet and determine this value, specifying it directly.
!> If your MCU does not boot after swapping to the EFL wear-leveling driver, it's likely that the flash size is incorrectly detected, usually as an MCU with larger flash and may require overriding.
@@ -139,7 +147,7 @@ Configurable options in your keyboard's `config.h`:
------------------------------------------|----------------------------|--------------------------------------------------------------------------------------------------------------------------------
`#define WEAR_LEVELING_RP2040_FLASH_SIZE` | `PICO_FLASH_SIZE_BYTES` | Number of bytes of flash on the board.
`#define WEAR_LEVELING_RP2040_FLASH_BASE` | `(flash_size-sector_size)` | The byte-wise location that the backing storage should be located.
-`#define WEAR_LEVELING_LOGICAL_SIZE` | `4096` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
+`#define WEAR_LEVELING_LOGICAL_SIZE` | `(backing_size/2)` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
`#define WEAR_LEVELING_BACKING_SIZE` | `8192` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size as well as the sector size.
`#define BACKING_STORE_WRITE_SIZE` | `2` | The write width used whenever a write is performed on the external flash peripheral.
diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
index 1719807e2688..74be33cdd47b 100644
--- a/docs/feature_auto_shift.md
+++ b/docs/feature_auto_shift.md
@@ -133,7 +133,17 @@ groups in the below fallback switch.
### NO_AUTO_SHIFT_SPECIAL (simple define)
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
-and /?
+/?, and the KC_TAB.
+
+### NO_AUTO_SHIFT_TAB (simple define)
+
+Do not Auto Shift KC_TAB but leave Auto Shift enabled for the other special
+characters.
+
+### NO_AUTO_SHIFT_SYMBOLS (simple define)
+
+Do not Auto Shift symbol keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
+and /?.
### NO_AUTO_SHIFT_NUMERIC (simple define)
@@ -143,9 +153,13 @@ Do not Auto Shift numeric keys, zero through nine.
Do not Auto Shift alpha characters, which include A through Z.
+### AUTO_SHIFT_ENTER (simple define)
+
+Auto Shift the enter key.
+
### Auto Shift Per Key
-There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
+There are functions that allows you to determine which keys should be autoshifted, much like the tap-hold keys.
The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`:
@@ -166,15 +180,21 @@ For more granular control, there is `get_auto_shifted_key`. The default function
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
# ifndef NO_AUTO_SHIFT_ALPHA
- case KC_A ... KC_Z:
+ case AUTO_SHIFT_ALPHA:
# endif
# ifndef NO_AUTO_SHIFT_NUMERIC
- case KC_1 ... KC_0:
+ case AUTO_SHIFT_NUMERIC:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
+# ifndef NO_AUTO_SHIFT_TAB
case KC_TAB:
- case KC_MINUS ... KC_SLASH:
- case KC_NONUS_BACKSLASH:
+# endif
+# ifndef NO_AUTO_SHIFT_SYMBOLS
+ case AUTO_SHIFT_SYMBOLS:
+# endif
+# endif
+# ifdef AUTO_SHIFT_ENTER
+ case KC_ENT:
# endif
return true;
}
@@ -192,6 +212,25 @@ Enables keyrepeat.
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
+
+### AUTO_SHIFT_ALPHA (predefined key group)
+
+A predefined group of keys representing A through Z.
+
+### AUTO_SHIFT_NUMERIC (predefined key group)
+
+A predefined group of keys representing 0 through 9. Note, these are defined as
+1 through 0 since that is the order they normally appear in.
+
+### AUTO_SHIFT_SYMBOLS (predefined key group)
+
+A predefined group of keys representing symbolic characters which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
+and /?.
+
+### AUTO_SHIFT_SPECIAL (predefined key group)
+
+A predefined group of keys that combines AUTO_SHIFT_SYMBOLS and KC_TAB.
+
## Custom Shifted Values
Especially on small keyboards, the default shifted value for many keys is not
@@ -271,10 +310,16 @@ generating taps on release. For example:
#define RETRO_SHIFT 500
```
+Without a value set, holds of any length without an interrupting key will produce the shifted value.
+
This value (if set) must be greater than one's `TAPPING_TERM`, as the key press
must be designated as a 'hold' by `process_tapping` before we send the modifier.
+[Per-key tapping terms](tap_hold.md#tapping-term) can be used as a workaround.
There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys.
+**Note:** Tap Holds must be added to Auto Shift, see [here.](feature_auto_shift.md#auto-shift-per-key)
+`IS_RETRO` may be helpful if one wants all Tap Holds retro shifted.
+
### Retro Shift and Tap Hold Configurations
Tap Hold Configurations work a little differently when using Retro Shift.
diff --git a/docs/feature_autocorrect.md b/docs/feature_autocorrect.md
index 9f80c93f8274..3a0a49095c6b 100644
--- a/docs/feature_autocorrect.md
+++ b/docs/feature_autocorrect.md
@@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
### Apply Autocorrect
-Additionally, `apply_autocorrect(uint8_t backspaces, const char *str)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word).
+Additionally, `apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word), and the typo and corrected strings (complete words).
+
+?> Due to the way code works (no notion of words, just a stream of letters), the `typo` and `correct` strings are a best bet and could be "wrong". For example you may get `wordtpyo` & `wordtypo` instead of the expected `tpyo` & `typo`.
#### Apply Autocorrect Example
@@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut
float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
#endif
-bool apply_autocorrect(uint8_t backspaces, const char *str) {
+bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef AUDIO_ENABLE
PLAY_SONG(autocorrect_song);
#endif
@@ -223,14 +225,17 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) {
?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters.
-!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` or `SEND_STRING`.
+!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` nor `SEND_STRING`.
You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
```c
-bool apply_autocorrect(uint8_t backspaces, const char *str) {
+bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef OLED_ENABLE
oled_write_P(PSTR("Auto-corrected"), false);
+#endif
+#ifdef CONSOLE_ENABLE
+ printf("'%s' was corrected to '%s'\n", typo, correct);
#endif
return true;
}
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index 24057c608f8c..69391fcefe99 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -1,12 +1,12 @@
# Backlighting :id=backlighting
-Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
+Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB Underglow](feature_rgblight.md) and [RGB Matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
-The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
+## Usage :id=usage
-Most keyboards have backlighting enabled by default if they support it, but if it is not working for you, check that your `rules.mk` includes the following:
+Most keyboards have backlighting enabled by default if they support it, but if it is not working for you (or you have added support), check that your `rules.mk` includes the following:
```make
BACKLIGHT_ENABLE = yes
@@ -14,86 +14,117 @@ BACKLIGHT_ENABLE = yes
## Keycodes :id=keycodes
-Once enabled, the following keycodes below can be used to change the backlight level.
+|Key |Aliases |Description |
+|-------------------------------|---------|-----------------------------------|
+|`QK_BACKLIGHT_TOGGLE` |`BL_TOGG`|Turn the backlight on or off |
+|`QK_BACKLIGHT_STEP` |`BL_STEP`|Cycle through backlight levels |
+|`QK_BACKLIGHT_ON` |`BL_ON` |Set the backlight to max brightness|
+|`QK_BACKLIGHT_OFF` |`BL_OFF` |Turn the backlight off |
+|`QK_BACKLIGHT_UP` |`BL_UP` |Increase the backlight level |
+|`QK_BACKLIGHT_DOWN` |`BL_DOWN`|Decrease the backlight level |
+|`QK_BACKLIGHT_TOGGLE_BREATHING`|`BL_BRTG`|Toggle backlight breathing |
-| Key | Aliases | Description |
-|---------------------------------|-----------|-------------------------------------|
-| `QK_BACKLIGHT_TOGGLE` | `BL_TOGG` | Turn the backlight on or off |
-| `QK_BACKLIGHT_STEP` | `BL_STEP` | Cycle through backlight levels |
-| `QK_BACKLIGHT_ON` | `BL_ON` | Set the backlight to max brightness |
-| `QK_BACKLIGHT_OFF` | `BL_OFF` | Turn the backlight off |
-| `QK_BACKLIGHT_UP` | `BL_UP` | Increase the backlight level |
-| `QK_BACKLIGHT_DOWN` | `BL_DOWN` | Decrease the backlight level |
-| `QK_BACKLIGHT_TOGGLE_BREATHING` | `BL_BRTG` | Toggle backlight breathing |
+## Basic Configuration :id=basic-configuration
-## Functions :id=functions
-
-These functions can be used to change the backlighting in custom code:
-
-|Function |Description |
-|------------------------|--------------------------------------------|
-|`backlight_toggle()` |Turn the backlight on or off |
-|`backlight_enable()` |Turn the backlight on |
-|`backlight_disable()` |Turn the backlight off |
-|`backlight_step()` |Cycle through backlight levels |
-|`backlight_increase()` |Increase the backlight level |
-|`backlight_decrease()` |Decrease the backlight level |
-|`backlight_level(x)` |Sets the backlight level to specified level |
-|`get_backlight_level()` |Return the current backlight level |
-|`is_backlight_enabled()`|Return whether the backlight is currently on|
-
-If backlight breathing is enabled (see below), the following functions are also available:
-
-|Function |Description |
-|---------------------|--------------------------------------|
-|`breathing_toggle()` |Turn the backlight breathing on or off|
-|`breathing_enable()` |Turns on backlight breathing |
-|`breathing_disable()`|Turns off backlight breathing |
-
-## Configuration :id=configuration
-
-To select which driver to use, configure your `rules.mk` with the following:
-
-```make
-BACKLIGHT_DRIVER = software
-```
-
-Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help on individual drivers.
-
-To configure the backlighting, `#define` these in your `config.h`:
+Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|------------------|-----------------------------------------------------------------------------------------------------------------|
-|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LED(s) |
+|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LEDs |
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|`BACKLIGHT_CAPS_LOCK` |*Not defined* |Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported |
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|`BACKLIGHT_ON_STATE` |`1` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|`BACKLIGHT_LIMIT_VAL` |`255` |The maximum duty cycle of the backlight -- `255` allows for full brightness, any lower will decrease the maximum.|
+|`BACKLIGHT_DEFAULT_ON` |`true` |Enable backlight upon clearing the EEPROM |
+|`BACKLIGHT_DEFAULT_BREATHING`|`false` |Whether to enable backlight breathing upon clearing the EEPROM |
|`BACKLIGHT_DEFAULT_LEVEL` |`BACKLIGHT_LEVELS`|The default backlight level to use upon clearing the EEPROM |
-|`BACKLIGHT_DEFAULT_BREATHING`|*Not defined* |Whether to enable backlight breathing upon clearing the EEPROM |
Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`.
-### Backlight On State :id=backlight-on-state
+### "On" State :id=on-state
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
-This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
+To configure the "on" state of the backlight circuit, add the following to your `config.h`:
+
+```c
+#define BACKLIGHT_ON_STATE 0
+```
+
+### Multiple Backlight Pins :id=multiple-backlight-pins
+
+Most keyboards have only one backlight pin which controls all backlight LEDs (especially if the backlight is connected to a hardware PWM pin).
+The `timer` and `software` drivers allow you to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
+
+This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
+
+To configure multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
+
+```c
+#define BACKLIGHT_PINS { F5, B2 }
+```
+
+## Driver Configuration :id=driver-configuration
+
+Backlight driver selection is configured in `rules.mk`. Valid drivers are `pwm` (default), `timer`, `software`, or `custom`. See below for information on individual drivers.
-### AVR Driver :id=avr-driver
+### PWM Driver :id=pwm-driver
-The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
+This is the default backlight driver, which leverages the hardware PWM output capability of the microcontroller.
```make
BACKLIGHT_DRIVER = pwm
```
-#### Caveats :id=avr-caveats
+### Timer Driver :id=timer-driver
+
+This driver is similar to the PWM driver, but instead of directly configuring the pin to output a PWM signal, an interrupt handler is attached to the timer to turn the pin on and off as appropriate.
+
+```make
+BACKLIGHT_DRIVER = timer
+```
+
+### Software Driver :id=software-driver
+
+In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. However, breathing is not supported, and the backlight can flicker when the keyboard is busy.
+
+```make
+BACKLIGHT_DRIVER = software
+```
+
+### Custom Driver :id=custom-driver
+
+If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using a simple API.
+
+```make
+BACKLIGHT_DRIVER = custom
+```
+
+```c
+void backlight_init_ports(void) {
+ // Optional - runs on startup
+ // Usually you want to configure pins here
+}
+void backlight_set(uint8_t level) {
+ // Optional - runs on level change
+ // Usually you want to respond to the new value
+}
+
+void backlight_task(void) {
+ // Optional - runs periodically
+ // Note that this is called in the main keyboard loop,
+ // so long running actions here can cause performance issues
+}
+```
+
+## AVR Configuration :id=avr-configuration
+
+### PWM Driver :id=avr-pwm-driver
-On AVR boards, QMK automatically decides which driver to use according to the following table:
+The following table describes the supported pins for the PWM driver. Only cells marked with a timer number are capable of hardware PWM output; any others must use the `timer` driver.
|Backlight Pin|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
|-------------|-------------|----------|-------------|-------------|---------|-----------|
@@ -108,113 +139,171 @@ On AVR boards, QMK automatically decides which driver to use according to the fo
|`D4` | | | | |Timer 1 | |
|`D5` | | | | |Timer 1 | |
-All other pins will use timer-assisted software PWM:
+### Timer Driver :id=avr-timer-driver
-|Audio Pin|Audio Timer|Software PWM Timer|
-|---------|-----------|------------------|
-|`C4` |Timer 3 |Timer 1 |
-|`C5` |Timer 3 |Timer 1 |
-|`C6` |Timer 3 |Timer 1 |
-|`B5` |Timer 1 |Timer 3 |
-|`B6` |Timer 1 |Timer 3 |
-|`B7` |Timer 1 |Timer 3 |
+Any GPIO pin can be used with this driver. The following table describes the supported timers:
-When both timers are in use for Audio, the backlight PWM cannot use a hardware timer, and will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
+|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
+|-------------|----------|-------------|-------------|---------|-----------|
+|Timers 1 & 3 |Timer 1 |Timers 1 & 3 |Timer 1 |Timer 1 |Timer 1 |
-#### Hardware PWM Implementation :id=hardware-pwm-implementation
+The following `#define`s apply only to the `timer` driver:
-When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
-The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
-In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus the brightness, where `0x0000` is completely off and `0xFFFF` is completely on.
+|Define |Default|Description |
+|-----------------------|-------|----------------|
+|`BACKLIGHT_PWM_TIMER` |`1` |The timer to use|
-The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
-In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
+Note that the choice of timer may conflict with the [Audio](feature_audio.md) feature.
-#### Timer Assisted PWM Implementation :id=timer-assisted-implementation
+## ChibiOS/ARM Configuration :id=arm-configuration
-When `BACKLIGHT_PIN` is not set to a hardware backlight pin, QMK will use a hardware timer configured to trigger software interrupts. This time will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
-When resetting to 0, the CPU will fire an OVF (overflow) interrupt that will turn the LEDs on, starting the duty cycle.
-The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the CPU will fire a Compare Output match interrupt, which will turn the LEDs off.
-In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus the brightness, where `0x0000` is completely off and `0xFFFF` is completely on.
+### PWM Driver :id=arm-pwm-driver
-The breathing effect is the same as in the hardware PWM implementation.
+Depending on the ChibiOS board configuration, you may need to enable PWM at the keyboard level. For STM32, this would look like:
-### ARM Driver :id=arm-configuration
+`halconf.h`:
+```c
+#define HAL_USE_PWM TRUE
+```
+`mcuconf.h`:
+```c
+#undef STM32_PWM_USE_TIM4
+#define STM32_PWM_USE_TIM4 TRUE
+```
-While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
+The following `#define`s apply only to the `pwm` driver:
-```make
-BACKLIGHT_DRIVER = pwm
+|Define |Default |Description |
+|-----------------------|-------------|---------------------------------------------------------------|
+|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use |
+|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
+|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use |
+|`BACKLIGHT_PWM_PERIOD` |*Not defined*|The PWM period in counter ticks - Default is platform dependent|
+
+
+Refer to the ST datasheet for your particular MCU to determine these values. For example, these defaults are set up for pin `B8` on a Proton-C (STM32F303) using `TIM4_CH3` on AF2. Unless you are designing your own keyboard, you generally should not need to change them.
+
+### Timer Driver :id=arm-timer-driver
+
+Depending on the ChibiOS board configuration, you may need to enable general-purpose timers at the keyboard level. For STM32, this would look like:
+
+`halconf.h`:
+```c
+#define HAL_USE_GPT TRUE
+```
+`mcuconf.h`:
+```c
+#undef STM32_GPT_USE_TIM15
+#define STM32_GPT_USE_TIM15 TRUE
```
-#### ChibiOS Configuration :id=arm-configuration
+The following `#define`s apply only to the `timer` driver:
-The following `#define`s apply only to ARM-based keyboards:
+|Define |Default |Description |
+|----------------------|--------|----------------|
+|`BACKLIGHT_GPT_DRIVER`|`GPTD15`|The timer to use|
-|Define |Default|Description |
-|-----------------------|-------|-----------------------------------|
-|`BACKLIGHT_PWM_DRIVER` |`PWMD4`|The PWM driver to use |
-|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
-|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use|
+## Example Schematic
-See the ST datasheet for your particular MCU to determine these values. Unless you are designing your own keyboard, you generally should not need to change them.
+Since the MCU can only supply so much current to its GPIO pins, instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
-#### Caveats :id=arm-caveats
+In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
+A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
+The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
-Currently only hardware PWM is supported, not timer assisted, and does not provide automatic configuration.
+![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)
-### Software PWM Driver :id=software-pwm-driver
+## API :id=api
-In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your `rules.mk`:
+### `void backlight_toggle(void)` :id=api-backlight-toggle
-```make
-BACKLIGHT_DRIVER = software
-```
+Toggle the backlight on or off.
-#### Multiple Backlight Pins :id=multiple-backlight-pins
+---
-Most keyboards have only one backlight pin which controls all backlight LEDs (especially if the backlight is connected to a hardware PWM pin).
-In software PWM, it is possible to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
+### `void backlight_enable(void)` :id=api-backlight-enable
-This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
+Turn the backlight on.
-To activate multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
+---
-```c
-#define BACKLIGHT_PINS { F5, B2 }
-```
+### `void backlight_disable(void)` :id=api-backlight-disable
-### Custom Driver :id=custom-driver
+Turn the backlight off.
-If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using this simple API provided by QMK. To enable, add this to your `rules.mk`:
+---
-```make
-BACKLIGHT_DRIVER = custom
-```
+### `void backlight_step(void)` :id=api-backlight-step
-Then implement any of these hooks:
+Cycle through backlight levels.
-```c
-void backlight_init_ports(void) {
- // Optional - runs on startup
- // Usually you want to configure pins here
-}
-void backlight_set(uint8_t level) {
- // Optional - runs on level change
- // Usually you want to respond to the new value
-}
+---
-void backlight_task(void) {
- // Optional - runs periodically
- // Note that this is called in the main keyboard loop,
- // so long running actions here can cause performance issues
-}
-```
+### `void backlight_increase(void)` :id=api-backlight-increase
-## Example Schematic
+Increase the backlight level.
-In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
-A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
-The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
+---
-![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)
+### `void backlight_decrease(void)` :id=api-backlight-decrease
+
+Decrease the backlight level.
+
+---
+
+### `void backlight_level(uint8_t level)` :id=api-backlight-level
+
+Set the backlight level.
+
+#### Arguments :id=api-backlight-level-arguments
+
+ - `uint8_t level`
+ The level to set, from 0 to `BACKLIGHT_LEVELS`.
+
+---
+
+### `uint8_t get_backlight_level(void)` :id=api-get-backlight-level
+
+Get the current backlight level.
+
+#### Return Value :id=api-get-backlight-level-return
+
+The current backlight level, from 0 to `BACKLIGHT_LEVELS`.
+
+---
+
+### `bool is_backlight_enabled(void)` :id=api-is-backlight-enabled
+
+Get the current backlight state.
+
+#### Return Value :id=api-is-backlight-enabled-return
+
+`true` if the backlight is enabled.
+
+---
+
+### `void backlight_toggle_breathing(void)` :id=api-backlight-toggle-breathing
+
+Toggle backlight breathing on or off.
+
+---
+
+### `void backlight_enable_breathing(void)` :id=api-backlight-enable-breathing
+
+Turn backlight breathing on.
+
+---
+
+### `void backlight_disable_breathing(void)` :id=api-backlight-disable-breathing
+
+Turn backlight breathing off.
+
+---
+
+### `bool is_backlight_breathing(void)` :id=api-is-backlight-breathing
+
+Get the current backlight breathing state.
+
+#### Return Value :id=api-is-backlight-breathing-return
+
+`true` if backlight breathing is enabled.
diff --git a/docs/feature_bluetooth.md b/docs/feature_bluetooth.md
index f7ded84d8679..5fac06fba756 100644
--- a/docs/feature_bluetooth.md
+++ b/docs/feature_bluetooth.md
@@ -4,10 +4,10 @@
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
-|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
-|----------------------------------------------------------------|--------------------|---------------|--------------------------------|--------------|
-|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = RN42` |RN-42 |
-|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = BluefruitLE`|nRF51822 |
+|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
+|----------------------------------------------------------------|--------------------|---------------|---------------------------------|--------------|
+|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = rn42` |RN-42 |
+|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = bluefruit_le`|nRF51822 |
Not Supported Yet but possible:
* [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479). [Possible tmk implementation found in](https://github.com/tmk/tmk_keyboard/issues/514)
@@ -32,7 +32,7 @@ Add the following to your `rules.mk`:
```make
BLUETOOTH_ENABLE = yes
-BLUETOOTH_DRIVER = BluefruitLE # or RN42
+BLUETOOTH_DRIVER = bluefruit_le # or rn42
```
## Bluetooth Keycodes
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index fd241061fbf4..2e802446b6b4 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -345,10 +345,9 @@ is not set, all other layers will reference themselves.
}
return layer; // important if default is not in case.
}
-
```
-
- The equivalent definition using the combo macros is this:
+
+The equivalent definition using the combo macros is this:
```c
COMBO_REF_LAYER(_DVORAK, _QWERTY)
diff --git a/docs/feature_converters.md b/docs/feature_converters.md
index b1abfa373ad8..11bdbed576b5 100644
--- a/docs/feature_converters.md
+++ b/docs/feature_converters.md
@@ -1,12 +1,10 @@
# Converters
-Since many drop-in replacement controllers now exist, we've done our best to make them easy to use in existing designs.
+This page documents the automated process for converting keyboards to use drop-in replacement controllers. This process is designed to be easy to use and can be completed in a few simple steps.
-This page documents the handy automated process for converting keyboards.
+## Supported Converters
-### Supported Converters
-
-Currently the following converters are available:
+The following converters are available at this time:
| From | To |
|------------|-------------------|
@@ -28,14 +26,10 @@ Currently the following converters are available:
| `elite_c` | `helios` |
| `elite_c` | `liatris` |
-See below for more in depth information on each converter.
## Overview
-Each converter category is broken down by its declared `pin compatibility`.
-This ensures that only valid combinations are attempted.
-
-You can generate the firmware by appending `-e CONVERT_TO=` to your compile/flash command. For example:
+Each converter category is broken down by its declared `pin compatibility`. This ensures that only valid combinations are attempted. You can generate the firmware by appending `-e CONVERT_TO=` to your compile/flash command. For example:
```sh
qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c
@@ -59,14 +53,12 @@ Once a converter is enabled, it exposes the `CONVERT_TO_` flag
### Pin Compatibility
-To ensure compatibility, provide validation, and power future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`.
-
-Currently the following pin compatibility interfaces are defined:
+To ensure compatibility, provide validation, and enable future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`. The following pin compatibility interfaces are currently defined:
-| Pinout | Notes |
-|------------|-----------------------------------|
-| `promicro` | Includes RX/TX LEDs |
-| `elite_c` | Includes bottom row pins, no LEDs |
+| Pin Compatibility | Notes |
+|-------------------|-----------------------------------|
+| `promicro` | Includes RX/TX LEDs |
+| `elite_c` | Includes bottom row pins, no LEDs |
To declare the base for conversions, add this line to your keyboard's `rules.mk`:
@@ -140,7 +132,7 @@ The following defaults are based on what has been implemented for [RP2040](platf
### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi :id=promicro_rp2040
-Currently identical to [Adafruit KB2040](#kb2040).
+Feature set is identical to [Adafruit KB2040](#kb2040).
### STeMCell :id=stemcell
@@ -150,9 +142,7 @@ There are two versions of STeMCell available, with different pinouts:
- v2.0.0 (pre-release v1.0.1, v1.0.2)
Default official firmware only supports v2.0.0 STeMCell.
-STeMCell has support to swap UART and I2C pins, to enable single-wire uart communication in STM chips.
-
-The following additional flags has to be used while compiling, based on the pin used for split communication.
+STeMCell has support to swap UART and I2C pins to enable single-wire uart communication in STM chips. The following additional flags has to be used while compiling, based on the pin used for split communication:
| Split Pin | Compile flags |
|-----------|---------------|
@@ -173,11 +163,8 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
-Feature set currently identical to [Adafruit KB2040](#kb2040).
-
-Enables VBUS detection by default for superior split keyboard support.
+Feature set is identical to [Adafruit KB2040](#kb2040). VBUS detection is enabled by default for superior split keyboard support. For more information, refer to the [Community Edition pinout](platformdev_rp2040.md#rp2040_ce) docs.
-For more information, refer to the [RP2040 Community Edition](platformdev_rp2040.md#rp2040_ce) docs.
## Elite-C
@@ -202,8 +189,8 @@ Converter summary:
### STeMCell :id=stemcell_elite
-Currently identical to [STeMCell](#stemcell) with support for the additional bottom row of pins.
+Identical to [Pro Micro - STeMCell](#stemcell) with support for the additional bottom row of pins.
### RP2040 Community Edition :id=rp2040_ce_elite
-Currently identical to [RP2040 Community Edition](#rp2040_ce), with support for the additional bottom row of pins.
+Identical to [Pro Micro - RP2040 Community Edition](#rp2040_ce) with support for the additional bottom row of pins.
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 891baeefa1d0..4eeb388e5776 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -82,10 +82,10 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
```c
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
- [_BASE] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
- [_LOWER] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) },
- [_RAISE] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) },
- [_ADJUST] = { ENCODER_CCW_CW(RGB_RMOD, RGB_MOD), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) },
+ [0] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
+ [1] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) },
+ [2] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) },
+ [3] = { ENCODER_CCW_CW(RGB_RMOD, RGB_MOD), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) },
};
#endif
```
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index b456bad736f8..68145edd6cca 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -4,11 +4,12 @@
The following options are currently available for haptic feedback in `rules.mk`:
-```
+```make
HAPTIC_ENABLE = yes
-HAPTIC_DRIVER += DRV2605L
-HAPTIC_DRIVER += SOLENOID
+HAPTIC_DRIVER = drv2605l
+# or
+HAPTIC_DRIVER = solenoid
```
The following `config.h` settings are available for all types of haptic feedback:
@@ -92,30 +93,30 @@ This driver supports 2 different feedback motors. Set the following in your `con
Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.
-```
-#define FB_ERM_LRA 0
-#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
-#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
+```c
+#define DRV2605L_FB_ERM_LRA 0
+#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
+#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
/* Please refer to your datasheet for the optimal setting for your specific motor. */
-#define RATED_VOLTAGE 3
-#define V_PEAK 5
+#define DRV2605L_RATED_VOLTAGE 3
+#define DRV2605L_V_PEAK 5
```
##### LRA
Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.
-```
-#define FB_ERM_LRA 1
-#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
-#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
+```c
+#define DRV2605L_FB_ERM_LRA 1
+#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
+#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
/* Please refer to your datasheet for the optimal setting for your specific motor. */
-#define RATED_VOLTAGE 2
-#define V_PEAK 2.8
-#define V_RMS 2.0
-#define V_PEAK 2.1
-#define F_LRA 205 /* resonance freq */
+#define DRV2605L_RATED_VOLTAGE 2
+#define DRV2605L_V_PEAK 2.8
+#define DRV2605L_V_RMS 2.0
+#define DRV2605L_V_PEAK 2.1
+#define DRV2605L_F_LRA 205 /* resonance freq */
```
#### DRV2605L waveform library
@@ -170,13 +171,13 @@ List of waveform sequences from the datasheet:
| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
### Optional DRV2605L defines
-```
-#define DRV_GREETING *sequence name or number*
+```c
+#define DRV2605L_GREETING *sequence name or number*
```
If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
-```
-#define DRV_MODE_DEFAULT *sequence name or number*
+```c
+#define DRV2605L_DEFAULT_MODE *sequence name or number*
```
This will set what sequence `HF_RST` will set as the active mode. If not defined, mode will be set to 1 when `HF_RST` is pressed.
diff --git a/docs/feature_hd44780.md b/docs/feature_hd44780.md
index 4ade640baae7..dcbd656bbee4 100644
--- a/docs/feature_hd44780.md
+++ b/docs/feature_hd44780.md
@@ -1,6 +1,6 @@
-# HD44780 LCD Driver
+# HD44780 LCD Driver :id=hd44780-lcd-driver
-## Supported Hardware
+## Supported Hardware :id=supported-hardware
LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) IC or equivalent, communicating in 4-bit mode.
@@ -11,7 +11,7 @@ LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
To run these modules at 3.3V, an additional MAX660 voltage converter IC must be soldered on, along with two 10µF capacitors. See [this page](https://www.codrey.com/electronic-circuits/hack-your-16x2-lcd/) for more details.
-## Usage
+## Usage :id=usage
Add the following to your `rules.mk`:
@@ -19,7 +19,7 @@ Add the following to your `rules.mk`:
HD44780_ENABLE = yes
```
-## Basic Configuration
+## Basic Configuration :id=basic-configuration
Add the following to your `config.h`:
@@ -33,9 +33,9 @@ Add the following to your `config.h`:
|`HD44780_DISPLAY_LINES`|`2` |The number of visible lines on the display |
|`HD44780_WRAP_LINES` |*Not defined* |If defined, input characters will wrap to the next line |
-## Examples
+## Examples :id=examples
-### Hello World
+### Hello World :id=example-hello-world
Add the following to your `keymap.c`:
@@ -46,7 +46,7 @@ void keyboard_post_init_user(void) {
}
```
-### Custom Character Definition
+### Custom Character Definition :id=example-custom-character
Up to eight custom characters can be defined. This data is stored in the Character Generator RAM (CGRAM), and is not persistent across power cycles.
@@ -77,15 +77,15 @@ void keyboard_post_init_user(void) {
}
```
-## API
+## API :id=api
-### `void hd44780_init(bool cursor, bool blink)`
+### `void hd44780_init(bool cursor, bool blink)` :id=api-hd44780-init
Initialize the display.
This function should be called only once, before any of the other functions can be called.
-#### Arguments
+#### Arguments :id=api-hd44780-init-arguments
- `bool cursor`
Whether to show the cursor.
@@ -94,7 +94,7 @@ This function should be called only once, before any of the other functions can
---
-### `void hd44780_clear(void)`
+### `void hd44780_clear(void)` :id=api-hd44780-clear
Clear the display.
@@ -102,7 +102,7 @@ This function is called on init.
---
-### `void hd44780_home(void)`
+### `void hd44780_home(void)` :id=api-hd44780-home
Move the cursor to the home position.
@@ -110,13 +110,13 @@ This function is called on init.
---
-### `void hd44780_on(bool cursor, bool blink)`
+### `void hd44780_on(bool cursor, bool blink)` :id=api-hd44780-on
Turn the display on, and/or set the cursor properties.
This function is called on init.
-#### Arguments
+#### Arguments :id=api-hd44780-on-arguments
- `bool cursor`
Whether to show the cursor.
@@ -125,17 +125,17 @@ This function is called on init.
---
-### `void hd44780_off(void)`
+### `void hd44780_off(void)` :id=api-hd44780-off
Turn the display off.
---
-### `void hd44780_set_cursor(uint8_t col, uint8_t line)`
+### `void hd44780_set_cursor(uint8_t col, uint8_t line)` :id=api-hd44780-set-cursor
Move the cursor to the specified position on the display.
-#### Arguments
+#### Arguments :id=api-hd44780-set-cursor-arguments
- `uint8_t col`
The column number to move to, from 0 to 15 on 16x2 displays.
@@ -144,48 +144,48 @@ Move the cursor to the specified position on the display.
---
-### `void hd44780_putc(char c)`
+### `void hd44780_putc(char c)` :id=api-hd44780-putc
Print a character to the display. The newline character `\n` will move the cursor to the start of the next line.
The exact character shown may depend on the ROM code of your particular display - refer to the datasheet for the full character set.
-#### Arguments
+#### Arguments :id=api-hd44780-putc-arguments
- `char c`
The character to print.
---
-### `void hd44780_puts(const char *s)`
+### `void hd44780_puts(const char *s)` :id=api-hd44780-puts
Print a string of characters to the display.
-#### Arguments
+#### Arguments :id=api-hd44780-puts-arguments
- `const char *s`
The string to print.
---
-### `void hd44780_puts_P(const char *s)`
+### `void hd44780_puts_P(const char *s)` :id=api-hd44780-puts-p
Print a string of characters from PROGMEM to the display.
On ARM devices, this function is simply an alias of `hd44780_puts()`.
-#### Arguments
+#### Arguments :id=api-hd44780-puts-p-arguments
- `const char *s`
The PROGMEM string to print (ie. `PSTR("Hello")`).
---
-### `void hd44780_define_char(uint8_t index, uint8_t *data)`
+### `void hd44780_define_char(uint8_t index, uint8_t *data)` :id=api-hd44780-define-char
Define a custom character.
-#### Arguments
+#### Arguments :id=api-hd44780-define-char-arguments
- `uint8_t index`
The index of the custom character to define, from 0 to 7.
@@ -194,13 +194,13 @@ Define a custom character.
---
-### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)`
+### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)` :id=api-hd44780-define-char-p
Define a custom character from PROGMEM.
On ARM devices, this function is simply an alias of `hd44780_define_char()`.
-#### Arguments
+#### Arguments :id=api-hd44780-define-char-p-arguments
- `uint8_t index`
The index of the custom character to define, from 0 to 7.
@@ -209,21 +209,21 @@ On ARM devices, this function is simply an alias of `hd44780_define_char()`.
---
-### `bool hd44780_busy(void)`
+### `bool hd44780_busy(void)` :id=api-hd44780-busy
Indicates whether the display is currently processing, and cannot accept instructions.
-#### Return Value
+#### Return Value :id=api-hd44780-busy-arguments
`true` if the display is busy.
---
-### `void hd44780_write(uint8_t data, bool isData)`
+### `void hd44780_write(uint8_t data, bool isData)` :id=api-hd44780-write
Write a byte to the display.
-#### Arguments
+#### Arguments :id=api-hd44780-write-arguments
- `uint8_t data`
The byte to send to the display.
@@ -232,67 +232,67 @@ Write a byte to the display.
---
-### `uint8_t hd44780_read(bool isData)`
+### `uint8_t hd44780_read(bool isData)` :id=api-hd44780-read
Read a byte from the display.
-#### Arguments
+#### Arguments :id=api-hd44780-read-arguments
- `bool isData`
Whether to read the current cursor position, or the character at the cursor.
-#### Return Value
+#### Return Value :id=api-hd44780-read-return
If `isData` is `true`, the returned byte will be the character at the current DDRAM address. Otherwise, it will be the current DDRAM address and the busy flag.
---
-### `void hd44780_command(uint8_t command)`
+### `void hd44780_command(uint8_t command)` :id=api-hd44780-command
Send a command to the display. Refer to the datasheet and `hd44780.h` for the valid commands and defines.
This function waits for the display to clear the busy flag before sending the command.
-#### Arguments
+#### Arguments :id=api-hd44780-command-arguments
- `uint8_t command`
The command to send.
---
-### `void hd44780_data(uint8_t data)`
+### `void hd44780_data(uint8_t data)` :id=api-hd44780-data
Send a byte of data to the display.
This function waits for the display to clear the busy flag before sending the data.
-#### Arguments
+#### Arguments :id=api-hd44780-data-arguments
- `uint8_t data`
The byte of data to send.
---
-### `void hd44780_set_cgram_address(uint8_t address)`
+### `void hd44780_set_cgram_address(uint8_t address)` :id=api-hd44780-set-cgram-address
Set the CGRAM address.
This function is used when defining custom characters.
-#### Arguments
+#### Arguments :id=api-hd44780-set-cgram-address-arguments
- `uint8_t address`
The CGRAM address to move to, from `0x00` to `0x3F`.
---
-### `void hd44780_set_ddram_address(uint8_t address)`
+### `void hd44780_set_ddram_address(uint8_t address)` :id=api-hd44780-set-ddram-address
Set the DDRAM address.
This function is used when printing characters to the display, and setting the cursor.
-#### Arguments
+#### Arguments :id=api-hd44780-set-ddram-address-arguments
- `uint8_t address`
The DDRAM address to move to, from `0x00` to `0x7F`.
diff --git a/docs/feature_key_overrides.md b/docs/feature_key_overrides.md
index 608eb001e4b8..59eced95c364 100644
--- a/docs/feature_key_overrides.md
+++ b/docs/feature_key_overrides.md
@@ -21,7 +21,7 @@ Then, in your `keymap.c` file, you'll need to define the array `key_overrides`,
The `key_override_t` struct has many options that allow you to precisely tune your overrides. The full reference is shown below. Instead of manually creating a `key_override_t` value, it is recommended to use these dedicated initializers:
#### `ko_make_basic(modifiers, key, replacement)`
-Returns a `key_override_t`, which sends `replacement` (can be a key-modifer combination), when `key` and `modifiers` are all pressed down. This override still activates if any additional modifiers not specified in `modifiers` are also pressed down. See `ko_make_with_layers_and_negmods` to customize this behavior.
+Returns a `key_override_t`, which sends `replacement` (can be a key-modifier combination), when `key` and `modifiers` are all pressed down. This override still activates if any additional modifiers not specified in `modifiers` are also pressed down. See `ko_make_with_layers_and_negmods` to customize this behavior.
#### `ko_make_with_layers(modifiers, key, replacement, layers)`
Additionally takes a bitmask `layers` that defines on which layers the override is used.
@@ -224,4 +224,31 @@ The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT
## Difference to Combos :id=difference-to-combos
-Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interacton with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable.
+Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interaction with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable.
+
+## Solution to the problem of flashing modifiers :id=neutralize-flashing-modifiers
+
+If the programs you use bind an action to taps of modifier keys (e.g. tapping left GUI to bring up the applications menu or tapping left Alt to focus the menu bar), you may find that using key overrides with suppressed mods falsely triggers those actions. To counteract this, you can define a `DUMMY_MOD_NEUTRALIZER_KEYCODE` in `config.h` that will get sent in between the register and unregister events of a suppressed modifier. That way, the programs on your computer will no longer interpret the mod suppression induced by key overrides as a lone tap of a modifier key and will thus not falsely trigger the undesired action.
+
+Naturally, for this technique to be effective, you must choose a `DUMMY_MOD_NEUTRALIZER_KEYCODE` for which no keyboard shortcuts are bound to. Recommended values are: `KC_RIGHT_CTRL` or `KC_F18`.
+Please note that `DUMMY_MOD_NEUTRALIZER_KEYCODE` must be a basic, unmodified, HID keycode so values like `KC_NO`, `KC_TRANSPARENT` or `KC_PIPE` aka `S(KC_BACKSLASH)` are not permitted.
+
+By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your `config.h`:
+
+```c
+#define MODS_TO_NEUTRALIZE { , , ... }
+```
+
+Examples:
+
+```c
+#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL
+
+// Neutralize left alt and left GUI (Default value)
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) }
+
+// Neutralize left alt, left GUI, right GUI and left Control+Shift
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) }
+```
+
+!> Do not use `MOD_xxx` constants like `MOD_LSFT` or `MOD_RALT`, since they're 5-bit packed bit-arrays while `MODS_TO_NEUTRALIZE` expects a list of 8-bit packed bit-arrays. Use `MOD_BIT()` or `MOD_MASK_xxx` instead.
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 86dff89eca94..b1ce09d34946 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -12,21 +12,20 @@ There is basic support for addressable LED matrix lighting with the I2C IS31FL37
```make
LED_MATRIX_ENABLE = yes
-LED_MATRIX_DRIVER = IS31FL3731
+LED_MATRIX_DRIVER = is31fl3731
```
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
-| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `LED_DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
+| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
-| `LED_DRIVER_ADDR_1` | (Required) Address for the first LED driver | |
-| `LED_DRIVER_ADDR_2` | (Optional) Address for the second LED driver | |
-| `LED_DRIVER_ADDR_3` | (Optional) Address for the third LED driver | |
-| `LED_DRIVER_ADDR_4` | (Optional) Address for the fourth LED driver | |
+| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first LED driver | |
+| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second LED driver | |
+| `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third LED driver | |
+| `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth LED driver | |
Here is an example using 2 drivers.
@@ -34,14 +33,15 @@ Here is an example using 2 drivers.
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
-// 0b1110100 AD <-> GND
-// 0b1110111 AD <-> VCC
-// 0b1110101 AD <-> SCL
-// 0b1110110 AD <-> SDA
-#define LED_DRIVER_ADDR_1 0b1110100
-#define LED_DRIVER_ADDR_2 0b1110110
-
-#define LED_DRIVER_COUNT 2
+// 00 AD <-> GND
+// 01 AD <-> SCL
+// 10 AD <-> SDA
+// 11 AD <-> VCC
+// ADDR represents A1:A0 of the 7-bit address.
+// The result is: 0b11101(ADDR)
+#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
+#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
+
#define LED_DRIVER_1_LED_TOTAL 25
#define LED_DRIVER_2_LED_TOTAL 24
#define LED_MATRIX_LED_COUNT (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)
@@ -49,12 +49,12 @@ Here is an example using 2 drivers.
!> Note the parentheses, this is so when `LED_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)` will give very different results than `rand() % LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL`.
-For split keyboards using `LED_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
+For split keyboards using `LED_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `IS31FL3731_I2C_ADDRESS_1` for one and `IS31FL3731_I2C_ADDRESS_2` for the other one. Then, in `g_is31fl3731_leds`, fill out the correct driver index (0 or 1). If using one address, use `IS31FL3731_I2C_ADDRESS_1` for both, and use index 0 for `g_is31fl3731_leds`.
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
+const is31fl3731_led_t PROGMEM g_is31fl3731_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@@ -94,7 +94,6 @@ Configure the hardware via your `config.h`:
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first LED driver | |
| `DRIVER_ADDR_` | (Required) Address for the additional LED drivers | |
@@ -127,7 +126,6 @@ Here is an example using 2 drivers.
```c
#define DRIVER_ADDR_2 0b0100001
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -139,7 +137,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led __flash g_is31_leds[LED_MATRIX_LED_COUNT] = {
+const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@@ -158,8 +156,8 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `.c`:
```c
-const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
- * LED Index
+const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
+/* LED Index
* | Scaling
* | | */
{5, 120},
@@ -247,19 +245,17 @@ enum led_matrix_effects {
LED_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom
LED_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in
LED_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard
-#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
LED_MATRIX_SOLID_REACTIVE_SIMPLE, // Pulses keys hit then fades out
- LED_MATRIX_SOLID_REACTIVE_WIDE // Value pulses near a single key hit then fades out
- LED_MATRIX_SOLID_REACTIVE_MULTIWIDE // Value pulses near multiple key hits then fades out
- LED_MATRIX_SOLID_REACTIVE_CROSS // Value pulses the same column and row of a single key hit then fades out
- LED_MATRIX_SOLID_REACTIVE_MULTICROSS // Value pulses the same column and row of multiple key hits then fades out
- LED_MATRIX_SOLID_REACTIVE_NEXUS // Value pulses away on the same column and row of a single key hit then fades out
- LED_MATRIX_SOLID_REACTIVE_MULTINEXUS // Value pulses away on the same column and row of multiple key hits then fades out
+ LED_MATRIX_SOLID_REACTIVE_WIDE, // Value pulses near a single key hit then fades out
+ LED_MATRIX_SOLID_REACTIVE_MULTIWIDE, // Value pulses near multiple key hits then fades out
+ LED_MATRIX_SOLID_REACTIVE_CROSS, // Value pulses the same column and row of a single key hit then fades out
+ LED_MATRIX_SOLID_REACTIVE_MULTICROSS, // Value pulses the same column and row of multiple key hits then fades out
+ LED_MATRIX_SOLID_REACTIVE_NEXUS, // Value pulses away on the same column and row of a single key hit then fades out
+ LED_MATRIX_SOLID_REACTIVE_MULTINEXUS, // Value pulses away on the same column and row of multiple key hits then fades out
LED_MATRIX_SOLID_SPLASH, // Value pulses away from a single key hit then fades out
LED_MATRIX_SOLID_MULTISPLASH, // Value pulses away from multiple key hits then fades out
-#endif
- 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_WAVE_LEFT_RIGHT, // Sine wave scrolling from left to right
+ LED_MATRIX_WAVE_UP_DOWN, // Sine wave scrolling from up to down
LED_MATRIX_EFFECT_MAX
};
```
@@ -281,8 +277,6 @@ 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` |
-?> These modes don't require any additional defines.
-
|Reactive Defines |Description |
|-------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
@@ -295,7 +289,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_LED_MATRIX_SOLID_SPLASH` |Enables `LED_MATRIX_SOLID_SPLASH` |
|`#define ENABLE_LED_MATRIX_SOLID_MULTISPLASH` |Enables `LED_MATRIX_SOLID_MULTISPLASH` |
-?> These modes also require the `LED_MATRIX_KEYPRESSES` or `LED_MATRIX_KEYRELEASES` define to be available.
+?> These modes introduce additional logic that can increase firmware size.
## Custom LED Matrix Effects :id=custom-led-matrix-effects
@@ -361,19 +355,18 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
## Additional `config.h` Options :id=additional-configh-options
```c
-#define LED_MATRIX_KEYPRESSES // reacts to keypresses
-#define LED_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
-#define LED_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
+#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_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define LED_MATRIX_LED_PROCESS_LIMIT (LED_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
#define LED_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
#define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs
+#define LED_MATRIX_DEFAULT_ON true // Sets the default enabled state, if none has been set
#define LED_MATRIX_DEFAULT_MODE LED_MATRIX_SOLID // Sets the default mode, if none has been set
#define LED_MATRIX_DEFAULT_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define LED_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define LED_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
- // If LED_MATRIX_KEYPRESSES or LED_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
+ // If reactive effects are enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
```
## EEPROM storage :id=eeprom-storage
diff --git a/docs/feature_macros.md b/docs/feature_macros.md
index 08310555fb77..c7d6c1a918a5 100644
--- a/docs/feature_macros.md
+++ b/docs/feature_macros.md
@@ -27,7 +27,7 @@ You can define up to 32 macros in a `keymap.json` file, as used by [Configurator
],
[
{"action":"tap", "keycodes": ["F1"]},
- {"action":"delay", "duration": "1000"},
+ {"action":"delay", "duration": 1000},
{"action":"tap", "keycodes": ["PGDN"]}
]
],
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index eed4f4f4aaaf..42448325c9f6 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -67,6 +67,7 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|`MOUSEKEY_TIME_TO_MAX` |30 |Time until maximum cursor speed is reached |
|`MOUSEKEY_WHEEL_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements |
+|`MOUSEKEY_WHEEL_DELTA` |1 |Wheel movement step size |
|`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached |
@@ -101,7 +102,7 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
Tips:
* The smoothness of the cursor movement depends on the `MOUSEKEY_INTERVAL` setting. The shorter the interval is set the smoother the movement will be. Setting the value too low makes the cursor unresponsive. Lower settings are possible if the micro processor is fast enough. For example: At an interval of `8` milliseconds, `125` movements per second will be initiated. With a base speed of `1000` each movement will move the cursor by `8` pixels.
-* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `2`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
+* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
### Constant mode
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index a62294b23a62..5a583fd40eee 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -10,6 +10,7 @@ Tested combinations:
|SSD1306 |128x32 |AVR |Primary support |
|SSD1306 |128x64 |AVR |Verified working |
|SSD1306 |128x32 |Arm | |
+|SSD1306 |128x64 |Arm |Verified working |
|SH1106 |128x64 |AVR |No scrolling |
|SH1107 |64x128 |AVR |No scrolling |
|SH1107 |64x128 |Arm |No scrolling |
@@ -29,17 +30,17 @@ OLED_ENABLE = yes
|OLED Driver |Supported Device |
|-------------------|------------------------------------|
-|SSD1306 (default) |For both SSD1306, SH1106, and SH1107|
+|`ssd1306` (default)|For both SSD1306, SH1106, and SH1107|
e.g.
```make
-OLED_DRIVER = SSD1306
+OLED_DRIVER = ssd1306
```
|OLED Transport | |
|---------------|------------------------------------------------|
-|i2c (default) | Uses I2C for communication with the OLED panel |
-|spi | Uses SPI for communication with the OLED panel |
+|`i2c` (default)| Uses I2C for communication with the OLED panel |
+|`spi` | Uses SPI for communication with the OLED panel |
e.g.
```make
@@ -166,6 +167,28 @@ bool oled_task_user(void) {
#endif
```
+Render a message before booting into bootloader mode.
+```c
+void oled_render_boot(bool bootloader) {
+ oled_clear();
+ for (int i = 0; i < 16; i++) {
+ oled_set_cursor(0, i);
+ if (bootloader) {
+ oled_write_P(PSTR("Awaiting New Firmware "), false);
+ } else {
+ oled_write_P(PSTR("Rebooting "), false);
+ }
+ }
+
+ oled_render_dirty(true);
+}
+
+bool shutdown_user(bool jump_to_bootloader) {
+ oled_render_boot(jump_to_bootloader);
+}
+
+```
+
## Basic Configuration
These configuration options should be placed in `config.h`. Example:
@@ -190,7 +213,7 @@ These configuration options should be placed in `config.h`. Example:
|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|`OLED_UPDATE_INTERVAL` |`0` (`50` for split keyboards) |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
-|`OLED_UPDATE_PROCESS_LIMIT'|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
+|`OLED_UPDATE_PROCESS_LIMIT`|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
### I2C Configuration
|Define |Default |Description |
@@ -275,7 +298,7 @@ Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, beca
## OLED API
```c
-// OLED rotation enum values are flags
+// OLED Rotation enum values are flags
typedef enum {
OLED_ROTATION_0 = 0,
OLED_ROTATION_90 = 1,
@@ -283,7 +306,7 @@ typedef enum {
OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180
} oled_rotation_t;
-// Initialize the OLED display, rotating the rendered output based on the define passed in.
+// Initialize the oled display, rotating the rendered output based on the define passed in.
// Returns true if the OLED was initialized successfully
bool oled_init(oled_rotation_t rotation);
@@ -301,8 +324,12 @@ bool oled_send_data(const uint8_t *data, uint16_t size);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void oled_clear(void);
-// Renders the dirty chunks of the buffer to OLED display
-void oled_render(void);
+// Alias to oled_render_dirty to avoid a change in api.
+#define oled_render() oled_render_dirty(false)
+
+// Renders all dirty blocks to the display at one time or a subset depending on the value of
+// all.
+void oled_render_dirty(bool all);
// Moves cursor to character position indicated by column and line, wraps if out of bounds
// Max column denoted by 'oled_max_chars()' and max lines by 'oled_max_lines()' functions
@@ -333,8 +360,6 @@ void oled_write_ln(const char *data, bool invert);
// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
// Useful for moving the screen in preparation for new drawing
-// oled_scroll_left or oled_scroll_right should be preferred for all cases of moving a static
-// image such as a logo or to avoid burn-in as it's much, much less cpu intensive
void oled_pan(bool left);
// Returns a pointer to the requested start index in the buffer plus remaining
@@ -351,6 +376,7 @@ void oled_write_raw_byte(const char data, uint16_t index);
// Coordinates start at top-left and go right and down for positive x and y
void oled_write_pixel(uint8_t x, uint8_t y, bool on);
+#if defined(__AVR__)
// Writes a PROGMEM string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Remapped to call 'void oled_write(const char *data, bool invert);' on ARM
@@ -364,6 +390,11 @@ void oled_write_ln_P(const char *data, bool invert);
// Writes a PROGMEM string to the buffer at current cursor position
void oled_write_raw_P(const char *data, uint16_t size);
+#else
+# define oled_write_P(data, invert) oled_write(data, invert)
+# define oled_write_ln_P(data, invert) oled_write_ln(data, invert)
+# define oled_write_raw_P(data, size) oled_write_raw(data, size)
+#endif // defined(__AVR__)
// Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on
@@ -398,7 +429,7 @@ void oled_scroll_set_area(uint8_t start_line, uint8_t end_line);
// Sets scroll speed, 0-7, fastest to slowest. Default is three.
// Does not take effect until scrolling is either started or restarted
// the ssd1306 supports 8 speeds with the delay
-// listed below betwen each frame of the scrolling effect
+// listed below between each frame of the scrolling effect
// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
void oled_scroll_set_speed(uint8_t speed);
diff --git a/docs/feature_os_detection.md b/docs/feature_os_detection.md
index f32e419807f7..907638bcfae1 100644
--- a/docs/feature_os_detection.md
+++ b/docs/feature_os_detection.md
@@ -36,10 +36,15 @@ This time is quite short, probably hundreds of milliseconds, but this data may b
If OS is guessed incorrectly, you may want to collect data about USB setup packets to refine the detection logic.
-To do so in your `rules.mk` add:
+To do so in your `config.h` add:
+
+```c
+#define OS_DETECTION_DEBUG_ENABLE
+```
+
+And in your `rules.mk` add:
```make
-OS_DETECTION_DEBUG_ENABLE = yes
CONSOLE_ENABLE = yes
```
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index 909eff826de1..0ac0069ff8b6 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -74,6 +74,71 @@ The Analog Joystick is an analog (ADC) driven sensor. There are a variety of jo
| `ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` |
| `ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
+### Azoteq IQS5XX Trackpad
+
+To use a Azoteq IQS5XX trackpad, add this to your `rules.mk`:
+
+```make
+POINTING_DEVICE_DRIVER = azoteq_iqs5xx
+```
+
+This supports the IQS525, IQS550 and IQS572 controllers, with the latter two being used in the TPS43 and TPS65 trackpads.
+
+#### Device settings
+
+Specific device profiles are provided which set the required values for dimensions and resolution.
+
+| Setting | Description |
+| -------------------------------- | ---------------------------------------------------------- |
+| `AZOTEQ_IQS5XX_TPS43` | (Pick One) Sets resolution/mm to TPS43 specifications. |
+| `AZOTEQ_IQS5XX_TPS65` | (Pick One) Sets resolution/mm to TPS65 specifications. |
+
+?> If using one of the above defines you can skip to gesture settings.
+
+| Setting | Description | Default |
+| -------------------------------- | ---------------------------------------------------------- | ------------- |
+| `AZOTEQ_IQS5XX_WIDTH_MM` | (Required) Width of the trackpad sensor in millimeters. | _not defined_ |
+| `AZOTEQ_IQS5XX_HEIGHT_MM` | (Required) Height of the trackpad sensor in millimeters. | _not defined_ |
+| `AZOTEQ_IQS5XX_RESOLUTION_X` | (Optional) Specify X resolution for CPI calculation. | _not defined_ |
+| `AZOTEQ_IQS5XX_RESOLUTION_Y` | (Optional) Specify Y resolution for CPI calculation. | _not defined_ |
+
+**`AZOTEQ_IQS5XX_RESOLUTION_X/Y`** fall back resolutions are provided within the driver based on controller model.
+
+| I2C Setting | Description | Default |
+| ------------------------- | ------------------------------------------------------------------------------- | ------- |
+| `AZOTEQ_IQS5XX_ADDRESS` | (Optional) Sets the I2C Address for the Azoteq trackpad | `0xE8` |
+| `AZOTEQ_IQS5XX_TIMEOUT_MS`| (Optional) The timeout for i2c communication with in milliseconds. | `10` |
+
+#### Gesture settings
+
+| Setting | Description | Default |
+| ----------------------------------------- | ------------------------------------------------------------------------------------ | ----------- |
+| `AZOTEQ_IQS5XX_TAP_ENABLE` | (Optional) Enable single finger tap. (Left click) | `true` |
+| `AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE` | (Optional) Enable two finger tap. (Right click) | `true` |
+| `AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE` | (Optional) Emulates holding left click to select text. | `false` |
+| `AZOTEQ_IQS5XX_SWIPE_X_ENABLE` | (Optional) Enable swipe gestures X+ (Mouse Button 5) / X- (Mouse Button 4) | `false` |
+| `AZOTEQ_IQS5XX_SWIPE_Y_ENABLE` | (Optional) Enable swipe gestures Y+ (Mouse Button 3) / Y- (Mouse Button 6) | `false` |
+| `AZOTEQ_IQS5XX_ZOOM_ENABLE` | (Optional) Enable zoom gestures Zoom Out (Mouse Button 7) / Zoom In (Mouse Button 8) | `false` |
+| `AZOTEQ_IQS5XX_SCROLL_ENABLE` | (Optional) Enable scrolling using two fingers. | `true` |
+| `AZOTEQ_IQS5XX_TAP_TIME` | (Optional) Maximum time in ms for tap to be registered. | `150` |
+| `AZOTEQ_IQS5XX_TAP_DISTANCE` | (Optional) Maximum deviation in pixels before single tap is no longer valid. | `25` |
+| `AZOTEQ_IQS5XX_HOLD_TIME` | (Optional) Minimum time in ms for press and hold. | `300` |
+| `AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME` | (Optional) Maximum time to travel initial distance before swipe is registered. | `150` |
+| `AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before swipe is registered. | `300` |
+| `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME` | (Optional) Maximum time to travel consecutive distance before swipe is registered. | `0` |
+| `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE`| (Optional) Minimum travel in pixels before a consecutive swipe is registered. | `2000` |
+| `AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before scroll is registered. | `50` |
+| `AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before zoom is registered. | `50` |
+| `AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE` | (Optional) Maximum time to travel zoom distance before zoom is registered. | `25` |
+
+#### Rotation settings
+
+| Setting | Description | Default |
+| ---------------------------- | ---------------------------------------------------------- | ------------- |
+| `AZOTEQ_IQS5XX_ROTATION_90` | (Optional) Configures hardware for 90 degree rotation. | _not defined_ |
+| `AZOTEQ_IQS5XX_ROTATION_180` | (Optional) Configures hardware for 180 degree rotation. | _not defined_ |
+| `AZOTEQ_IQS5XX_ROTATION_270` | (Optional) Configures hardware for 270 degree rotation. | _not defined_ |
+
### Cirque Trackpad
To use the Cirque Trackpad sensor, add this to your `rules.mk`:
@@ -735,9 +800,11 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#### Set different target layer when a particular layer is active:
-The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
-*NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack* if something similar was to be done in `layer_state_set_user `state = remove_auto_mouse_layer(state, false)` should be used instead
-*ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*
+The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
+
+*NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack*, if something similar was to be done in `layer_state_set_user`, `state = remove_auto_mouse_layer(state, false)` should be used instead.
+
+*ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*.
```c
// in keymap.c
diff --git a/docs/feature_programmable_button.md b/docs/feature_programmable_button.md
index 43a9e7fc1602..091464e19c03 100644
--- a/docs/feature_programmable_button.md
+++ b/docs/feature_programmable_button.md
@@ -2,7 +2,7 @@
Programmable Buttons are keys that have no predefined meaning. This means they can be processed on the host side by custom software without the operating system trying to interpret them.
-The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x07`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`).
+The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x09`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`).
?> Currently there is no known support in Windows or macOS. It may be possible to write a custom HID driver to receive these usages, but this is out of the scope of the QMK documentation.
diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md
index e714d9b86763..766fd6fe78f5 100644
--- a/docs/feature_ps2_mouse.md
+++ b/docs/feature_ps2_mouse.md
@@ -155,6 +155,29 @@ In your keyboard config.h:
#endif
```
+### RP2040 PIO Version :id=rp2040-pio-version
+
+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.
+
+You may optionally switch the PIO peripheral used with the following define in config.h:
+```c
+#define PS2_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the PS2 implementation uses the PIO0 peripheral
+```
+
+Example info.json content:
+
+```json
+ "ps2": {
+ "clock_pin": "GP1",
+ "data_pin": "GP0",
+ "driver": "vendor",
+ "enabled": true,
+ "mouse_enabled": true
+ }
+```
+
## Additional Settings :id=additional-settings
### PS/2 Mouse Features :id=ps2-mouse-features
diff --git a/docs/feature_rawhid.md b/docs/feature_rawhid.md
index 558a23a80fb0..64cb42fdfee0 100644
--- a/docs/feature_rawhid.md
+++ b/docs/feature_rawhid.md
@@ -1,69 +1,156 @@
-# Raw HID
+# Raw HID :id=raw-hid
-Raw HID allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or changing RGB LED colors and modes.
+The Raw HID feature allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or sending useful metrics like CPU/RAM usage.
-There are two main components to getting raw HID working with your keyboard.
+In order to communicate with the keyboard using this feature, you will need to write a program that runs on the host. As such, some basic programming skills are required - more if you intend to implement complex behaviour.
-## Keyboard firmware
+## Usage :id=usage
-The implementation is fairly straightforward for the firmware.
-In your `rules.mk` add:
+Add the following to your `rules.mk`:
```make
RAW_ENABLE = yes
```
-In your `keymap.c` include `"raw_hid.h"` and implement the following:
+## Basic Configuration :id=basic-configuration
+
+By default, the HID Usage Page and Usage ID for the Raw HID interface are `0xFF60` and `0x61`. However, they can be changed if necessary by adding the following to your `config.h`:
+
+|Define |Default |Description |
+|----------------|--------|---------------------------------------|
+|`RAW_USAGE_PAGE`|`0xFF60`|The usage page of the Raw HID interface|
+|`RAW_USAGE_ID` |`0x61` |The usage ID of the Raw HID interface |
+
+## Sending Data to the Keyboard :id=sending-data-to-the-keyboard
+
+To send data to the keyboard, you must first find a library for communicating with HID devices in the programming language of your choice. Here are some examples:
+
+* **Node.js:** [node-hid](https://github.com/node-hid/node-hid)
+* **C/C++:** [hidapi](https://github.com/libusb/hidapi)
+* **Java:** [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java)
+* **Python:** [pyhidapi](https://pypi.org/project/hid/) and [pywinusb](https://pypi.org/project/pywinusb)
+
+Please refer to these libraries' own documentation for instructions on usage. Remember to close the device once you are finished with it!
+
+Next, you will need to know the USB Vendor and Product IDs of the device. These can easily be found by looking at your keyboard's `info.json`, under the `usb` object (alternatively, you can also use Device Manager on Windows, System Information on macOS, or `lsusb` on Linux). For example, the Vendor ID for the Planck Rev 6 is `0x03A8`, and the Product ID is `0xA4F9`.
+
+It's also a good idea to narrow down the list of potential HID devices the library may give you by filtering on the usage page and usage ID, to avoid accidentally opening the interface on the same device for the keyboard, or mouse, or media keys, etc.
+
+Once you are able to open the HID device and send reports to it, it's time to handle them on the keyboard side. Implement the following function in your `keymap.c` and start coding:
```c
void raw_hid_receive(uint8_t *data, uint8_t length) {
- // Your code goes here. data is the packet received from host.
+ // Your code goes here
+ // `data` is a pointer to the buffer containing the received HID report
+ // `length` is the length of the report - always `RAW_EPSIZE`
}
```
-The `"raw_hid.h"` header also declares `void raw_hid_send(uint8_t *data, uint8_t length);` which allows sending packets from keyboard to host. As an example, it can also be used for debugging when building your host application by returning all data back to the host.
+!> Because the HID specification does not support variable length reports, all reports in both directions must be exactly `RAW_EPSIZE` (currently 32) bytes long, regardless of actual payload length. However, variable length payloads can potentially be implemented on top of this by creating your own data structure that may span multiple reports.
+
+## Receiving Data from the Keyboard :id=receiving-data-from-the-keyboard
+
+If you need the keyboard to send data back to the host, simply call the `raw_hid_send()` function. It requires two arguments - a pointer to a 32-byte buffer containing the data you wish to send, and the length (which should always be `RAW_EPSIZE`).
+
+The received report can then be handled in whichever way your HID library provides.
+
+## Simple Example :id=simple-example
+
+The following example reads the first byte of the received report from the host, and if it is an ASCII "A", responds with "B". `memset()` is used to fill the response buffer (which could still contain the previous response) with null bytes.
```c
void raw_hid_receive(uint8_t *data, uint8_t length) {
- raw_hid_send(data, length);
+ uint8_t response[length];
+ memset(response, 0, length);
+ response[0] = 'B';
+
+ if(data[0] == 'A') {
+ raw_hid_send(response, length);
+ }
}
```
-These two functions send and receive packets of length `RAW_EPSIZE` bytes to and from the host (32 on LUFA/ChibiOS/V-USB, 64 on ATSAM).
+On the host side (here we are using Python and the `pyhidapi` library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent.
+
+For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed.
+
+```python
+import sys
+import hid
+
+vendor_id = 0x4335
+product_id = 0x0002
+
+usage_page = 0xFF60
+usage = 0x61
+report_length = 32
+
+def get_raw_hid_interface():
+ device_interfaces = hid.enumerate(vendor_id, product_id)
+ raw_hid_interfaces = [i for i in device_interfaces if i['usage_page'] == usage_page and i['usage'] == usage]
+
+ if len(raw_hid_interfaces) == 0:
+ return None
-Make sure to flash raw enabled firmware before proceeding with working on the host side.
+ interface = hid.Device(path=raw_hid_interfaces[0]['path'])
-## Host (Windows/macOS/Linux)
+ print(f"Manufacturer: {interface.manufacturer}")
+ print(f"Product: {interface.product}")
-This is the more complicated part as it will require some digging.
+ return interface
-To connect your host computer to your keyboard with raw HID you need four pieces of information about your keyboard:
+def send_raw_report(data):
+ interface = get_raw_hid_interface()
-1. Vendor ID
-2. Product ID
-3. Usage Page
-4. Usage
+ if interface is None:
+ print("No device found")
+ sys.exit(1)
+
+ request_data = [0x00] * (report_length + 1) # First byte is Report ID
+ request_data[1:len(data) + 1] = data
+ request_report = bytes(request_data)
+
+ print("Request:")
+ print(request_report)
+
+ try:
+ interface.write(request_report)
+
+ response_report = interface.read(report_length, timeout=1000)
+
+ print("Response:")
+ print(response_report)
+ finally:
+ interface.close()
+
+if __name__ == '__main__':
+ send_raw_report([
+ 0x41
+ ])
+```
-The first two can easily be found in your keyboard's `config.h` in the keyboard's main directory under `VENDOR_ID` and `PRODUCT_ID`.
+## API :id=api
-The final two can be overridden in your keyboard's `config.h` in the keyboard's main directory by redefining the values: `#define RAW_USAGE_PAGE 0xFF60` and `#define RAW_USAGE_ID 0x61`.
+### `void raw_hid_receive(uint8_t *data, uint8_t length)` :id=api-raw-hid-receive
-By default, **Usage Page** is `0xFF60` and **Usage** is `0x61`.
+Callback, invoked when a raw HID report has been received from the host.
-### Building your host
+#### Arguments :id=api-raw-hid-receive-arguments
-You can build your host using any language that has an available HID implementation library if you don't wish to make your own. The ones we know of for popular languages are:
+ - `uint8_t *data`
+ A pointer to the received data. Always 32 bytes in length.
+ - `uint8_t length`
+ The length of the buffer. Always 32.
-* Node: [node-hid](https://github.com/node-hid/node-hid).
-* C: [hidapi](https://github.com/libusb/hidapi).
-* Java: [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java).
-* Python: [pyhidapi](https://pypi.org/project/hid/).
+---
-This is not an exhaustive cross-platform list but should get you started. There are no special requirements for using raw HID so any HID library should work.
+### `void raw_hid_send(uint8_t *data, uint8_t length)` :id=api-raw-hid-send
-Now that you have all four pieces of information required to open HID interface to your keyboard. All you need to do is use your library's available functions to open the device with its ID parameters.
+Send an HID report.
-Note that Vendor ID and Product ID are not actually required to open the device. They are used only to filter to a specific device out of the many HID devices you have plugged in. Many libraries will give you the option to open the device using Product Name or Manufacturer Name instead, `node-hid` being a prime example. This will create issues for devices with builtin USB Hub or any extra HID interfaces where you will have multiple interfaces with the same name or from the same manufacturer. The Vendor ID together with Product ID create a unique designation to a single interface and will not exhibit this problem. Therefore, even if your library doesn't require you to, it is best to use them to avoid issues.
-Unlike Vendor ID and Product ID though, Usage Page and Usage are necessary for successful communication.
+#### Arguments :id=api-raw-hid-send-arguments
-It should go without saying that regardless of the library you're using, you should always make sure to close the interface when finished. Depending on the operating system and your particular environment there may be issues connecting to it again afterwards with another client or another instance of the same client if it's not explicitly closed.
+ - `uint8_t *data`
+ A pointer to the data to send. Must always be 32 bytes in length.
+ - `uint8_t length`
+ The length of the buffer. Must always be 32.
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index 822bc8f73485..824ff50648a2 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -12,22 +12,21 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = IS31FL3731
+RGB_MATRIX_DRIVER = is31fl3731
```
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
-| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `ISSI_3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `IS31FL3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
-| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
-| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
-| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
-| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
+| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
+| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
+| `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
+| `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
Here is an example using 2 drivers.
@@ -35,14 +34,15 @@ Here is an example using 2 drivers.
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
-// 0b1110100 AD <-> GND
-// 0b1110111 AD <-> VCC
-// 0b1110101 AD <-> SCL
-// 0b1110110 AD <-> SDA
-#define DRIVER_ADDR_1 0b1110100
-#define DRIVER_ADDR_2 0b1110110
-
-#define DRIVER_COUNT 2
+// 00 AD <-> GND
+// 01 AD <-> SCL
+// 10 AD <-> SDA
+// 11 AD <-> VCC
+// ADDR represents A1:A0 of the 7-bit address.
+// The result is: 0b11101(ADDR)
+#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
+#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
+
#define DRIVER_1_LED_TOTAL 25
#define DRIVER_2_LED_TOTAL 24
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -50,12 +50,12 @@ Here is an example using 2 drivers.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
-For split keyboards using `RGB_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
+For split keyboards using `RGB_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `IS31FL3731_I2C_ADDRESS_1` for one and `IS31FL3731_I2C_ADDRESS_2` for the other one. Then, in `g_is31fl3731_leds`, fill out the correct driver index (0 or 1). If using one address, use `IS31FL3731_I2C_ADDRESS_1` for both, and use index 0 for `g_is31fl3731_leds`.
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31fl3731_led_t PROGMEM g_is31fl3731_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -76,41 +76,40 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = IS31FL3733
+RGB_MATRIX_DRIVER = is31fl3733
```
You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
-| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
-| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
-| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `IS31FL3733_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `IS31FL3733_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `IS31FL3733_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
+| `IS31FL3733_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
+| `IS31FL3733_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
+| `IS31FL3733_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
-| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
-| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
-| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
-| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
-| `DRIVER_SYNC_1` | (Optional) Sync configuration for the first RGB driver | 0 |
-| `DRIVER_SYNC_2` | (Optional) Sync configuration for the second RGB driver | 0 |
-| `DRIVER_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 |
-| `DRIVER_SYNC_4` | (Optional) Sync configuration for the fourth RGB driver | 0 |
-
-The IS31FL3733 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
-
-| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
+| `IS31FL3733_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
+| `IS31FL3733_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
+| `IS31FL3733_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
+| `IS31FL3733_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
+| `IS31FL3733_SYNC_1` | (Optional) Sync configuration for the first RGB driver | 0 |
+| `IS31FL3733_SYNC_2` | (Optional) Sync configuration for the second RGB driver | 0 |
+| `IS31FL3733_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 |
+| `IS31FL3733_SYNC_4` | (Optional) Sync configuration for the fourth RGB driver | 0 |
+
+The IS31FL3733 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3733_SWPULLUP`/`IS31FL3733_CSPULLUP` are given the value of `IS31FL3733_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
+
+| `IS31FL3733_SWPULLUP/IS31FL3733_CSPULLUP` | Description |
|----------------------|-------------|
-| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
-| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_3KR` | The 3k Ohm resistor used at all times |
-| `PUR_4KR` | The 4k Ohm resistor used at all times |
-| `PUR_8KR` | The 8k Ohm resistor used at all times |
-| `PUR_16KR` | The 16k Ohm resistor used at all times |
-| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3733_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
+| `IS31FL3733_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3733_PUR_3KR` | The 3k Ohm resistor used at all times |
+| `IS31FL3733_PUR_4KR` | The 4k Ohm resistor used at all times |
+| `IS31FL3733_PUR_8KR` | The 8k Ohm resistor used at all times |
+| `IS31FL3733_PUR_16KR` | The 16k Ohm resistor used at all times |
+| `IS31FL3733_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
@@ -118,17 +117,16 @@ Here is an example using 2 drivers.
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
-// 00 <-> GND
-// 01 <-> SCL
-// 10 <-> SDA
-// 11 <-> VCC
+// 00 ADDRn <-> GND
+// 01 ADDRn <-> SCL
+// 10 ADDRn <-> SDA
+// 11 ADDRn <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b101(ADDR2)(ADDR1)
-#define DRIVER_ADDR_1 0b1010000
-#define DRIVER_ADDR_2 0b1010011
+#define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND
+#define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_VCC
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 58
#define DRIVER_2_LED_TOTAL 10
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -141,7 +139,7 @@ Currently only 4 drivers are supported, but it would be trivial to support all 8
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31fl3733_led_t PROGMEM g_is31fl3733_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -162,7 +160,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = IS31FL3736
+RGB_MATRIX_DRIVER = is31fl3736
```
You can use between 1 and 4 IS31FL3736 IC's. Do not specify `DRIVER_ADDR_` defines for IC's that are not present on your keyboard.
@@ -170,31 +168,30 @@ Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
-| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
-| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
-| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `IS31FL3736_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `IS31FL3736_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `IS31FL3736_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
+| `IS31FL3736_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
+| `IS31FL3736_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
+| `IS31FL3736_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
-| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
-| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
-| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
-| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
+| `IS31FL3736_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
+| `IS31FL3736_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
+| `IS31FL3736_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
+| `IS31FL3736_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
-The IS31FL3736 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
+The IS31FL3736 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3736_SWPULLUP`/`IS31FL3736_CSPULLUP` are given the value of `IS31FL3736_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
-| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
+| `IS31FL3736_SWPULLUP/IS31FL3736_CSPULLUP` | Description |
|----------------------|-------------|
-| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
-| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
-| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
-| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3736_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
+| `IS31FL3736_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3736_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3736_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3736_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3736_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
+| `IS31FL3736_PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
+| `IS31FL3736_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
@@ -202,16 +199,16 @@ Here is an example using 2 drivers.
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
-// 0000 <-> GND
-// 0101 <-> SCL
-// 1010 <-> SDA
-// 1111 <-> VCC
-// ADDR represents A3:A0 of the 7-bit address.
-// The result is: 0b101(ADDR)
-#define DRIVER_ADDR_1 0b1010000
-#define DRIVER_ADDR_2 0b1010001
+// 00 ADDRn <-> GND
+// 01 ADDRn <-> SCL
+// 10 ADDRn <-> SDA
+// 11 ADDRn <-> VCC
+// ADDR1 represents A1:A0 of the 7-bit address.
+// ADDR2 represents A3:A2 of the 7-bit address.
+// The result is: 0b101(ADDR2)(ADDR1)
+#define IS31FL3736_I2C_ADDRESS_1 IS31FL3736_I2C_ADDRESS_GND_GND
+#define IS31FL3736_I2C_ADDRESS_2 IS31FL3736_I2C_ADDRESS_GND_SCL
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -221,7 +218,7 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31fl3736_led_t PROGMEM g_is31fl3736_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -238,7 +235,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = IS31FL3737
+RGB_MATRIX_DRIVER = is31fl3737
```
You can use between 1 and 4 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_` defines for IC's that are not present on your keyboard.
@@ -246,31 +243,30 @@ Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
-| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 |
-| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
-| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `IS31FL3737_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `IS31FL3737_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `IS31FL3737_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 |
+| `IS31FL3737_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
+| `IS31FL3737_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
+| `IS31FL3737_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
-| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
-| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
-| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
-| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
+| `IS31FL3737_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
+| `IS31FL3737_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
+| `IS31FL3737_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
+| `IS31FL3737_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
-The IS31FL3737 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
+The IS31FL3737 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3737_SWPULLUP`/`IS31FL3737_CSPULLUP` are given the value of `IS31FL3737_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
-| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
+| `IS31FL3737_SWPULLUP/IS31FL3737_CSPULLUP` | Description |
|----------------------|-------------|
-| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
-| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
-| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
-| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
-| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3737_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
+| `IS31FL3737_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3737_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3737_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3737_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
+| `IS31FL3737_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
+| `IS31FL3737_PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
+| `IS31FL3737_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
@@ -278,16 +274,15 @@ Here is an example using 2 drivers.
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
-// 0000 <-> GND
-// 0101 <-> SCL
-// 1010 <-> SDA
-// 1111 <-> VCC
+// 0000 ADDR <-> GND
+// 0101 ADDR <-> SCL
+// 1010 ADDR <-> SDA
+// 1111 ADDR <-> VCC
// ADDR represents A3:A0 of the 7-bit address.
// The result is: 0b101(ADDR)
-#define DRIVER_ADDR_1 0b1010000
-#define DRIVER_ADDR_2 0b1010001
+#define IS31FL3737_I2C_ADDRESS_1 IS31FL3737_I2C_ADDRESS_GND
+#define IS31FL3737_I2C_ADDRESS_2 IS31FL3737_I2C_ADDRESS_SCL
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 36
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -297,7 +292,7 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31fl3737_led_t PROGMEM g_is31fl3737_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -338,7 +333,6 @@ Configure the hardware via your `config.h`:
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first RGB driver | |
| `DRIVER_ADDR_` | (Required) Address for the additional RGB drivers | |
@@ -373,7 +367,6 @@ Here is an example using 2 drivers.
```c
#define DRIVER_ADDR_2 0b0100001
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -386,7 +379,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led __flash g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -406,8 +399,8 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `.c`:
```c
-const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
- * LED Index
+const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
+/* LED Index
* | R scaling
* | | G scaling
* | | | B scaling
@@ -428,7 +421,7 @@ There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = WS2812
+RGB_MATRIX_DRIVER = ws2812
```
Configure the hardware via your `config.h`:
@@ -450,7 +443,7 @@ There is basic support for APA102 based addressable LED strands. To enable it, a
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = APA102
+RGB_MATRIX_DRIVER = apa102
```
Configure the hardware via your `config.h`:
@@ -465,41 +458,39 @@ Configure the hardware via your `config.h`:
```
---
-### AW20216 :id=aw20216
-There is basic support for addressable RGB matrix lighting with the SPI AW20216 RGB controller. To enable it, add this to your `rules.mk`:
+### AW20216S :id=aw20216s
+There is basic support for addressable RGB matrix lighting with the SPI AW20216S RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
-RGB_MATRIX_DRIVER = AW20216
+RGB_MATRIX_DRIVER = aw20216s
```
-You can use up to 2 AW20216 IC's. Do not specify `DRIVER__xxx` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
+You can use up to 2 AW20216S IC's. Do not specify `DRIVER__xxx` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
-| `DRIVER_1_CS` | (Required) MCU pin connected to first RGB driver chip select line | B13 |
-| `DRIVER_2_CS` | (Optional) MCU pin connected to second RGB driver chip select line | |
-| `DRIVER_1_EN` | (Required) MCU pin connected to first RGB driver hardware enable line | C13 |
-| `DRIVER_2_EN` | (Optional) MCU pin connected to second RGB driver hardware enable line | |
+| `AW20216S_CS_PIN_1` | (Required) MCU pin connected to first RGB driver chip select line | B13 |
+| `AW20216S_CS_PIN_2` | (Optional) MCU pin connected to second RGB driver chip select line | |
+| `AW20216S_EN_PIN_1` | (Required) MCU pin connected to first RGB driver hardware enable line | C13 |
+| `AW20216S_EN_PIN_2` | (Optional) MCU pin connected to second RGB driver hardware enable line | |
| `DRIVER_1_LED_TOTAL` | (Required) How many RGB lights are connected to first RGB driver | |
| `DRIVER_2_LED_TOTAL` | (Optional) How many RGB lights are connected to second RGB driver | |
-| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
-| `AW_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
-| `AW_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
-| `AW_SPI_MODE` | (Optional) Mode for SPI communication (0-3, defines polarity and phase of the clock) | 3 |
-| `AW_SPI_DIVISOR` | (Optional) Clock divisor for SPI communication (powers of 2, smaller numbers means faster communication, should not be less than 4) | 4 |
+| `AW20216S_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
+| `AW20216S_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
+| `AW20216S_SPI_MODE` | (Optional) Mode for SPI communication (0-3, defines polarity and phase of the clock) | 3 |
+| `AW20216S_SPI_DIVISOR` | (Optional) Clock divisor for SPI communication (powers of 2, smaller numbers means faster communication, should not be less than 4) | 4 |
Here is an example using 2 drivers.
```c
-#define DRIVER_1_CS B13
-#define DRIVER_2_CS B14
+#define AW20216S_CS_PIN_1 B13
+#define AW20216S_CS_PIN_2 B14
// Hardware enable lines may be connected to the same pin
-#define DRIVER_1_EN C13
-#define DRIVER_2_EN C13
+#define AW20216S_EN_PIN_1 C13
+#define AW20216S_EN_PIN_2 C13
-#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@@ -510,10 +501,10 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `.c`:
```c
-const aw_led PROGMEM g_aw_leds[RGB_MATRIX_LED_COUNT] = {
-/* Each AW20216 channel is controlled by a register at some offset between 0x00
+const aw20216s_led_t PROGMEM g_aw20216s_leds[RGB_MATRIX_LED_COUNT] = {
+/* Each AW20216S channel is controlled by a register at some offset between 0x00
* and 0xD7 inclusive.
- * See drivers/awinic/aw20216.h for the mapping between register offsets and
+ * See drivers/led/aw20216s.h for the mapping between register offsets and
* driver pin locations.
* driver
* | R location
@@ -642,6 +633,7 @@ enum rgb_matrix_effects {
RGB_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard
RGB_MATRIX_RAINBOW_BEACON, // Full tighter gradient spinning around center of keyboard
RGB_MATRIX_RAINBOW_PINWHEELS, // Full dual gradients spinning two halfs of keyboard
+ RGB_MATRIX_FLOWER_BLOOMING, // Full tighter gradient of first half scrolling left to right and second half scrolling right to left
RGB_MATRIX_RAINDROPS, // Randomly changes a single key's hue
RGB_MATRIX_JELLYBEAN_RAINDROPS, // Randomly changes a single key's hue and saturation
RGB_MATRIX_HUE_BREATHING, // Hue shifts up a slight ammount at the same time, then shifts back
@@ -650,24 +642,24 @@ enum rgb_matrix_effects {
RGB_MATRIX_PIXEL_FRACTAL, // Single hue fractal filled keys pulsing horizontally out to edges
RGB_MATRIX_PIXEL_FLOW, // Pulsing RGB flow along LED wiring with random hues
RGB_MATRIX_PIXEL_RAIN, // Randomly light keys with random hues
-#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
RGB_MATRIX_TYPING_HEATMAP, // How hot is your WPM!
RGB_MATRIX_DIGITAL_RAIN, // That famous computer simulation
-#endif
-#if defined(RGB_MATRIX_KEYPRESSES) || defined(RGB_MATRIX_KEYRELEASES)
RGB_MATRIX_SOLID_REACTIVE_SIMPLE, // Pulses keys hit to hue & value then fades value out
RGB_MATRIX_SOLID_REACTIVE, // Static single hue, pulses keys hit to shifted hue then fades to current hue
- RGB_MATRIX_SOLID_REACTIVE_WIDE // Hue & value pulse near a single key hit then fades value out
- RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE // Hue & value pulse near multiple key hits then fades value out
- RGB_MATRIX_SOLID_REACTIVE_CROSS // Hue & value pulse the same column and row of a single key hit then fades value out
- RGB_MATRIX_SOLID_REACTIVE_MULTICROSS // Hue & value pulse the same column and row of multiple key hits then fades value out
- RGB_MATRIX_SOLID_REACTIVE_NEXUS // Hue & value pulse away on the same column and row of a single key hit then fades value out
- RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS // Hue & value pulse away on the same column and row of multiple key hits then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_WIDE, // Hue & value pulse near a single key hit then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE, // Hue & value pulse near multiple key hits then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_CROSS, // Hue & value pulse the same column and row of a single key hit then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_MULTICROSS, // Hue & value pulse the same column and row of multiple key hits then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_NEXUS, // Hue & value pulse away on the same column and row of a single key hit then fades value out
+ RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS, // Hue & value pulse away on the same column and row of multiple key hits then fades value out
RGB_MATRIX_SPLASH, // Full gradient & value pulse away from a single key hit then fades value out
RGB_MATRIX_MULTISPLASH, // Full gradient & value pulse away from multiple key hits then fades value out
RGB_MATRIX_SOLID_SPLASH, // Hue & value pulse away from a single key hit then fades value out
RGB_MATRIX_SOLID_MULTISPLASH, // Hue & value pulse away from multiple key hits then fades value out
-#endif
+ RGB_MATRIX_STARLIGHT, // LEDs turn on and off at random at varying brightness, maintaining user set color
+ RGB_MATRIX_STARLIGHT_DUAL_HUE, // LEDs turn on and off at random at varying brightness, modifies user set hue by +- 30
+ RGB_MATRIX_STARLIGHT_DUAL_SAT, // LEDs turn on and off at random at varying brightness, modifies user set saturation by +- 30
+ RGB_MATRIX_RIVERFLOW, // Modification to breathing animation, offset's animation depending on key location to simulate a river flowing
RGB_MATRIX_EFFECT_MAX
};
```
@@ -698,6 +690,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_RGB_MATRIX_DUAL_BEACON` |Enables `RGB_MATRIX_DUAL_BEACON` |
|`#define ENABLE_RGB_MATRIX_RAINBOW_BEACON` |Enables `RGB_MATRIX_RAINBOW_BEACON` |
|`#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS` |Enables `RGB_MATRIX_RAINBOW_PINWHEELS` |
+|`#define ENABLE_RGB_MATRIX_FLOWER_BLOOMING` |Enables `RGB_MATRIX_FLOWER_BLOOMING` |
|`#define ENABLE_RGB_MATRIX_RAINDROPS` |Enables `RGB_MATRIX_RAINDROPS` |
|`#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS` |Enables `RGB_MATRIX_JELLYBEAN_RAINDROPS` |
|`#define ENABLE_RGB_MATRIX_HUE_BREATHING` |Enables `RGB_MATRIX_HUE_BREATHING` |
@@ -706,15 +699,17 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL` |Enables `RGB_MATRIX_PIXEL_FRACTAL` |
|`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` |
|`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` |
-
-?> These modes don't require any additional defines.
+|`#define ENABLE_RGB_MATRIX_STARLIGHT` |Enables `RGB_MATRIX_STARLIGHT` |
+|`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE` |Enables `RGB_MATRIX_STARLIGHT_DUAL_HUE` |
+|`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT` |Enables `RGB_MATRIX_STARLIGHT_DUAL_SAT` |
+|`#define ENABLE_RGB_MATRIX_RIVERFLOW` |Enables `RGB_MATRIX_RIVERFLOW` |
|Framebuffer Defines |Description |
|------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_RGB_MATRIX_TYPING_HEATMAP` |Enables `RGB_MATRIX_TYPING_HEATMAP` |
|`#define ENABLE_RGB_MATRIX_DIGITAL_RAIN` |Enables `RGB_MATRIX_DIGITAL_RAIN` |
-?> These modes also require the `RGB_MATRIX_FRAMEBUFFER_EFFECTS` define to be available.
+?> These modes introduce additional logic that can increase firmware size.
|Reactive Defines |Description |
|------------------------------------------------------|----------------------------------------------|
@@ -731,7 +726,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_RGB_MATRIX_SOLID_SPLASH` |Enables `RGB_MATRIX_SOLID_SPLASH` |
|`#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Enables `RGB_MATRIX_SOLID_MULTISPLASH` |
-?> These modes also require the `RGB_MATRIX_KEYPRESSES` or `RGB_MATRIX_KEYRELEASES` define to be available.
+?> These modes introduce additional logic that can increase firmware size.
### RGB Matrix Effect Typing Heatmap :id=rgb-matrix-effect-typing-heatmap
@@ -872,9 +867,7 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
## Additional `config.h` Options :id=additional-configh-options
```c
-#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
-#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
-#define RGB_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
+#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_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define RGB_MATRIX_LED_PROCESS_LIMIT (RGB_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
@@ -883,11 +876,12 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
#define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT // Sets the default mode, if none has been set
#define RGB_MATRIX_DEFAULT_HUE 0 // Sets the default hue value, if none has been set
#define RGB_MATRIX_DEFAULT_SAT 255 // Sets the default saturation value, if none has been set
+#define RGB_MATRIX_DEFAULT_ON true // Sets the default enabled state, if none has been set
#define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define RGB_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature)
#define RGB_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
- // If RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
+ // If reactive effects are enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
#define RGB_TRIGGER_ON_KEYDOWN // Triggers RGB keypress events on key down. This makes RGB control feel more responsive. This may cause RGB to not function properly on some boards
```
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index 948bbb241e3a..8a64454b0db5 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -28,7 +28,7 @@ For APA102 LEDs, add the following to your `rules.mk`:
```make
RGBLIGHT_ENABLE = yes
-RGBLIGHT_DRIVER = APA102
+RGBLIGHT_DRIVER = apa102
```
At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. For APA102 LEDs, you must also define the clock pin. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these.
@@ -102,6 +102,7 @@ Your RGB lighting can be configured by placing these `#define`s in your `config.
|`RGBLIGHT_DEFAULT_SAT` |`UINT8_MAX` (255) |The default saturation to use upon clearing the EEPROM |
|`RGBLIGHT_DEFAULT_VAL` |`RGBLIGHT_LIMIT_VAL` |The default value (brightness) to use upon clearing the EEPROM |
|`RGBLIGHT_DEFAULT_SPD` |`0` |The default speed to use upon clearing the EEPROM |
+|`RGBLIGHT_DEFAULT_ON` |`true` |Enable RGB lighting upon clearing the EEPROM |
## Effects and Animations
@@ -370,9 +371,9 @@ If you need to change your RGB lighting in code, for example in a macro to chang
Example:
```c
-sethsv(HSV_WHITE, (LED_TYPE *)&led[0]); // led 0
-sethsv(HSV_RED, (LED_TYPE *)&led[1]); // led 1
-sethsv(HSV_GREEN, (LED_TYPE *)&led[2]); // led 2
+sethsv(HSV_WHITE, (rgb_led_t *)&led[0]); // led 0
+sethsv(HSV_RED, (rgb_led_t *)&led[1]); // led 1
+sethsv(HSV_GREEN, (rgb_led_t *)&led[2]); // led 2
rgblight_set(); // Utility functions do not call rgblight_set() automatically, so they need to be called explicitly.
```
@@ -524,38 +525,6 @@ By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED
```
-For keyboards that use the RGB LEDs as a backlight for each key, you can also define it as in the example below.
-
-```c
-// config.h
-
-#define RGBLED_NUM 30
-
-/* RGB LED Conversion macro from physical array to electric array */
-#define LED_LAYOUT( \
- L00, L01, L02, L03, L04, L05, \
- L10, L11, L12, L13, L14, L15, \
- L20, L21, L22, L23, L24, L25, \
- L30, L31, L32, L33, L34, L35, \
- L40, L41, L42, L43, L44, L45 ) \
- { \
- L05, L04, L03, L02, L01, L00, \
- L10, L11, L12, L13, L14, L15, \
- L25, L24, L23, L22, L21, L20, \
- L30, L31, L32, L33, L34, L35, \
- L46, L45, L44, L43, L42, L41 \
- }
-
-/* RGB LED logical order map */
-/* Top->Bottom, Right->Left */
-#define RGBLIGHT_LED_MAP LED_LAYOUT( \
- 25, 20, 15, 10, 5, 0, \
- 26, 21, 16, 11, 6, 1, \
- 27, 22, 17, 12, 7, 2, \
- 28, 23, 18, 13, 8, 3, \
- 29, 24, 19, 14, 9, 4 )
-
-```
## Clipping Range
Using the `rgblight_set_clipping_range()` function, you can prepare more buffers than the actual number of LEDs, and output some of the buffers to the LEDs. This is useful if you want the split keyboard to treat left and right LEDs as logically contiguous.
@@ -575,11 +544,41 @@ In addition to setting the Clipping Range, you can use `RGBLIGHT_LED_MAP` togeth
#define RGBLED_NUM 8
#define RGBLIGHT_LED_MAP { 7, 6, 5, 4, 3, 2, 1, 0 }
-// some soruce
- rgblight_set_clipping_range(3, 4);
+// some source
+rgblight_set_clipping_range(3, 4);
```
## Hardware Modification
If your keyboard lacks onboard underglow LEDs, you may often be able to solder on an RGB LED strip yourself. You will need to find an unused pin to wire to the data pin of your LED strip. Some keyboards may break out unused pins from the MCU to make soldering easier. The other two pins, VCC and GND, must also be connected to the appropriate power pins.
+
+## Velocikey
+
+Velocikey is a feature that lets you control the speed of lighting effects (like the Rainbow Swirl effect) with the speed of your typing. The faster you type, the faster the lights will go!
+
+### Usage
+For Velocikey to take effect, there are two steps. First, when compiling your keyboard, you'll need to set `VELOCIKEY_ENABLE=yes` in `rules.mk`, e.g.:
+
+```
+MOUSEKEY_ENABLE = no
+STENO_ENABLE = no
+EXTRAKEY_ENABLE = yes
+VELOCIKEY_ENABLE = yes
+```
+
+Then, while using your keyboard, you need to also turn it on with the `VK_TOGG` keycode, which toggles the feature on and off.
+
+The following light effects will all be controlled by Velocikey when it is enabled:
+ - RGB Breathing
+ - RGB Rainbow Mood
+ - RGB Rainbow Swirl
+ - RGB Snake
+ - RGB Knight
+
+Support for LED breathing effects is planned but not available yet.
+
+ As long as Velocikey is enabled, it will control the speed regardless of any other speed setting that your RGB lights are currently on.
+
+ ### Configuration
+ Velocikey doesn't currently support any configuration via keyboard settings. If you want to adjust something like the speed increase or decay rate, you would need to edit `velocikey.c` and adjust the values there to achieve the kinds of speeds that you like.
diff --git a/docs/feature_send_string.md b/docs/feature_send_string.md
index 67df0224e93b..7d3f3ba32a15 100644
--- a/docs/feature_send_string.md
+++ b/docs/feature_send_string.md
@@ -1,4 +1,4 @@
-# Send String
+# Send String :id=send-string
The Send String API is part of QMK's macro system. It allows for sequences of keystrokes to be sent automatically.
@@ -6,7 +6,7 @@ The full ASCII character set is supported, along with all of the keycodes in the
?> Unicode characters are **not** supported with this API -- see the [Unicode](feature_unicode.md) feature instead.
-## Usage
+## Usage :id=usage
Send String is enabled by default, so there is usually no need for any special setup. However, if it is disabled, add the following to your `rules.mk`:
@@ -14,7 +14,7 @@ Send String is enabled by default, so there is usually no need for any special s
SEND_STRING_ENABLE = yes
```
-## Basic Configuration
+## Basic Configuration :id=basic-configuration
Add the following to your `config.h`:
@@ -23,7 +23,7 @@ Add the following to your `config.h`:
|`SENDSTRING_BELL`|*Not defined* |If the [Audio](feature_audio.md) feature is enabled, the `\a` character (ASCII `BEL`) will beep the speaker.|
|`BELL_SOUND` |`TERMINAL_SOUND`|The song to play when the `\a` character is encountered. By default, this is an eighth note of C5. |
-## Keycodes
+## Keycodes :id=keycodes
The Send String functions accept C string literals, but specific keycodes can be injected with the below macros. All of the keycodes in the [Basic Keycode range](keycodes_basic.md) are supported (as these are the only ones that will actually be sent to the host), but with an `X_` prefix instead of `KC_`.
@@ -44,13 +44,13 @@ The following characters are also mapped to their respective keycodes for conven
|`\t` |`\x1B`|`TAB`|`KC_TAB` |
| |`\x7F`|`DEL`|`KC_DELETE` |
-### Language Support
+### Language Support :id=language-support
By default, Send String assumes your OS keyboard layout is set to US ANSI. If you are using a different keyboard layout, you can [override the lookup tables used to convert ASCII characters to keystrokes](reference_keymap_extras.md#sendstring-support).
-## Examples
+## Examples :id=examples
-### Hello World
+### Hello World :id=example-hello-world
A simple custom keycode which types out "Hello, world!" and the Enter key when pressed.
@@ -70,7 +70,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
```
-### Keycode Injection
+### Keycode Injection :id=example-keycode-injection
This example types out opening and closing curly braces, then taps the left arrow key to move the cursor between the two.
@@ -84,26 +84,26 @@ This example types Ctrl+A, then Ctrl+C, without releasing Ctrl.
SEND_STRING(SS_LCTL("ac"));
```
-## API
+## API :id=api
-### `void send_string(const char *string)`
+### `void send_string(const char *string)` :id=api-send-string
Type out a string of ASCII characters.
This function simply calls `send_string_with_delay(string, 0)`.
-#### Arguments
+#### Arguments :id=api-send-string-arguments
- `const char *string`
The string to type out.
---
-### `void send_string_with_delay(const char *string, uint8_t interval)`
+### `void send_string_with_delay(const char *string, uint8_t interval)` :id=api-send-string-with-delay
Type out a string of ASCII characters, with a delay between each character.
-#### Arguments
+#### Arguments :id=api-send-string-with-delay-arguments
- `const char *string`
The string to type out.
@@ -112,26 +112,26 @@ Type out a string of ASCII characters, with a delay between each character.
---
-### `void send_string_P(const char *string)`
+### `void send_string_P(const char *string)` :id=api-send-string-p
Type out a PROGMEM string of ASCII characters.
On ARM devices, this function is simply an alias for `send_string_with_delay(string, 0)`.
-#### Arguments
+#### Arguments :id=api-send-string-p-arguments
- `const char *string`
The string to type out.
---
-### `void send_string_with_delay_P(const char *string, uint8_t interval)`
+### `void send_string_with_delay_P(const char *string, uint8_t interval)` :id=api-send-string-with-delay-p
Type out a PROGMEM string of ASCII characters, with a delay between each character.
On ARM devices, this function is simply an alias for `send_string_with_delay(string, interval)`.
-#### Arguments
+#### Arguments :id=api-send-string-with-delay-p-arguments
- `const char *string`
The string to type out.
@@ -140,76 +140,76 @@ On ARM devices, this function is simply an alias for `send_string_with_delay(str
---
-### `void send_char(char ascii_code)`
+### `void send_char(char ascii_code)` :id=api-send-char
Type out an ASCII character.
-#### Arguments
+#### Arguments :id=api-send-char-arguments
- `char ascii_code`
The character to type.
---
-### `void send_dword(uint32_t number)`
+### `void send_dword(uint32_t number)` :id=api-send-dword
Type out an eight digit (unsigned 32-bit) hexadecimal value.
The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`.
-#### Arguments
+#### Arguments :id=api-send-dword-arguments
- `uint32_t number`
The value to type, from 0 to 4,294,967,295.
---
-### `void send_word(uint16_t number)`
+### `void send_word(uint16_t number)` :id=api-send-word
Type out a four digit (unsigned 16-bit) hexadecimal value.
The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`.
-#### Arguments
+#### Arguments :id=api-send-word-arguments
- `uint16_t number`
The value to type, from 0 to 65,535.
---
-### `void send_byte(uint8_t number)`
+### `void send_byte(uint8_t number)` :id=api-send-bytes
Type out a two digit (8-bit) hexadecimal value.
The format is `[0-9a-f]{2}`, eg. `00` through `ff`.
-#### Arguments
+#### Arguments :id=api-send-byte-arguments
- `uint8_t number`
The value to type, from 0 to 255.
---
-### `void send_nibble(uint8_t number)`
+### `void send_nibble(uint8_t number)` :id=api-send-nibble
Type out a single hexadecimal digit.
The format is `[0-9a-f]{1}`, eg. `0` through `f`.
-#### Arguments
+#### Arguments :id=api-send-nibble-arguments
- `uint8_t number`
The value to type, from 0 to 15.
---
-### `void tap_random_base64(void)`
+### `void tap_random_base64(void)` :id=api-tap-random-base64
Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`.
---
-### `SEND_STRING(string)`
+### `SEND_STRING(string)` :id=api-send-string-macro
Shortcut macro for `send_string_with_delay_P(PSTR(string), 0)`.
@@ -217,7 +217,7 @@ On ARM devices, this define evaluates to `send_string_with_delay(string, 0)`.
---
-### `SEND_STRING_DELAY(string, interval)`
+### `SEND_STRING_DELAY(string, interval)` :id=api-send-string-delay-macro
Shortcut macro for `send_string_with_delay_P(PSTR(string), interval)`.
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index 1705ea922217..8f695a2b7c7d 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -205,7 +205,7 @@ This sets the pin to be used for serial communication. If you're not using seria
However, if you are using serial and I2C on the board, you will need to set this, and to something other than D0 and D1 (as these are used for I2C communication).
```c
-#define SELECT_SOFT_SERIAL_SPEED {#}`
+#define SELECT_SOFT_SERIAL_SPEED {#}
```
If you're having issues with serial communication, you can change this value, as it controls the communication speed for serial. The default is 1, and the possible values are:
@@ -298,7 +298,7 @@ This enables transmitting the pointing device status to the master side of the s
#define SPLIT_HAPTIC_ENABLE
```
-This enables triggering of haptic feedback on the slave side of the split keyboard. For DRV2605L this will send the mode, but for solenoids it is expected that the desired mode is already set up on the slave.
+This enables the triggering of haptic feedback on the slave side of the split keyboard. This will send information to the slave side such as the mode, dwell, and whether buzz is enabled.
```c
#define SPLIT_ACTIVITY_ENABLE
diff --git a/docs/feature_stenography.md b/docs/feature_stenography.md
index df4c9c6ad353..5ca3ea945fc1 100644
--- a/docs/feature_stenography.md
+++ b/docs/feature_stenography.md
@@ -104,7 +104,7 @@ After enabling stenography and optionally selecting a protocol, you may also nee
!> If you had *explicitly* set `VIRSTER_ENABLE = no`, none of the serial stenography protocols (GeminiPR, TX Bolt) will work properly. You are expected to either set it to `yes`, remove the line from your `rules.mk` or send the steno chords yourself in an alternative way using the [provided interceptable hooks](#interfacing-with-the-code).
-In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference) (you will need to include `keymap_steno.h`, see `planck/keymaps/steno/keymap.c` for an example). Remember to create a key to switch to the layer as well as a key for exiting the layer.
+In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference). Remember to create a key to switch to the layer as well as a key for exiting the layer.
Once you have your keyboard flashed, launch Plover. Click the 'Configure...' button. In the 'Machine' tab, select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control).
@@ -149,8 +149,6 @@ At the end of this scenario given as an example, `chord` would have five bits se
## Keycode Reference :id=keycode-reference
-You must include `keymap_steno.h` to your `keymap.c` with `#include "keymap_steno.h"` before you can use these keycodes
-
> Note: 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|
@@ -198,7 +196,7 @@ You must include `keymap_steno.h` to your `keymap.c` with `#include "keymap_sten
|`STN_RES2`||(Reset 2)|
|`STN_PWR`||(Power)|
-If you do not want to hit two keys with one finger combined keycodes can be used. These are also defined in `keymap_steno.h`, and causes both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
+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 |
|---------------|--------|----------|
diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md
index b7d8a5528fb8..42ea23396235 100644
--- a/docs/feature_tap_dance.md
+++ b/docs/feature_tap_dance.md
@@ -28,7 +28,7 @@ After this, you'll want to use the `tap_dance_actions` array to specify what act
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode).
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
-
+* `ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(on_each_tap_fn, on_each_release_fn, on_dance_finished_fn, on_dance_reset_fn)`: This macro is identical to `ACTION_TAP_DANCE_FN_ADVANCED` with the addition of `on_each_release_fn` which is invoked every time the key for the tap dance is released. It is worth noting that `on_each_release_fn` will still be called even when the key is released after the dance finishes (e.g. if the key is released after being pressed and held for longer than the `TAPPING_TERM`).
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
diff --git a/docs/feature_tri_layer.md b/docs/feature_tri_layer.md
index aa6c87719ca6..ade0040cc7b1 100644
--- a/docs/feature_tri_layer.md
+++ b/docs/feature_tri_layer.md
@@ -40,7 +40,7 @@ Eg, if you wanted to set the "Adjust" layer to be layer 5, you'd add this to you
| `set_tri_layer_lower_layer(layer)` | Changes the "lower" layer*. |
| `set_tri_layer_upper_layer(layer)` | Changes the "upper" layer*. |
| `set_tri_layer_adjust_layer(layer)` | Changes the "adjust" layer*. |
-| `set_tri_layer_layers(lower, upper, adjust)` | Stes the "lower", "upper" and "adjust" layers*. |
+| `set_tri_layer_layers(lower, upper, adjust)` | Sets the "lower", "upper" and "adjust" layers*. |
| `get_tri_layer_lower_layer()` | Gets the current "lower" layer. |
| `get_tri_layer_upper_layer()` | Gets the current "upper" layer. |
| `get_tri_layer_adjust_layer()` | Gets the current "adjust" layer. |
diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md
index 455596dab5e1..2c6d2ef002e5 100644
--- a/docs/feature_unicode.md
+++ b/docs/feature_unicode.md
@@ -1,48 +1,77 @@
-# Unicode Support
+# Unicode :id=unicode
-Unicode characters can be input straight from your keyboard! There are some limitations, however.
+With a little help from your OS, practically any Unicode character can be input using your keyboard.
-In order to enable Unicode support on your keyboard, you will need to do the following:
+## Caveats :id=caveats
-1. Choose one of three supported Unicode implementations: [Basic Unicode](#basic-unicode), [Unicode Map](#unicode-map), [UCIS](#ucis).
-2. Find which [input mode](#input-modes) is the best match for your operating system and setup.
-3. [Set](#setting-the-input-mode) the appropriate input mode (or modes) in your configuration.
-4. Add Unicode keycodes to your keymap.
+There are some limitations to this feature. Because there is no "standard" method of Unicode input across all operating systems, each of them require their own setup process on both the host *and* in the firmware, which may involve installation of additional software. This also means Unicode input will not "just work" when the keyboard is plugged into another device.
+## Usage :id=usage
-## 1. Methods :id=methods
+The core Unicode API can be used purely programmatically. However, there are also additional subsystems which build on top of it and come with keycodes to make things easier. See below for more details.
-QMK supports three different methods for enabling Unicode input and adding Unicode characters to your keymap. Each has its pros and cons in terms of flexibility and ease of use. Choose the one that best fits your use case.
+Add the following to your keymap's `rules.mk`:
-The Basic method should be enough for most users. However, if you need a wider range of supported characters (including emoji, rare symbols etc.), you should use Unicode Map.
+```make
+UNICODE_COMMON = yes
+```
+
+## Basic Configuration :id=basic-configuration
+
+Add the following to your `config.h`:
+
+|Define |Default |Description |
+|------------------------|------------------|--------------------------------------------------------------------------------|
+|`UNICODE_KEY_MAC` |`KC_LEFT_ALT` |The key to hold when beginning a Unicode sequence with the macOS input mode |
+|`UNICODE_KEY_LNX` |`LCTL(LSFT(KC_U))`|The key to tap when beginning a Unicode sequence with the Linux input mode |
+|`UNICODE_KEY_WINC` |`KC_RIGHT_ALT` |The key to hold when beginning a Unicode sequence with the WinCompose input mode|
+|`UNICODE_SELECTED_MODES`|`-1` |A comma separated list of input modes for cycling through |
+|`UNICODE_CYCLE_PERSIST` |`true` |Whether to persist the current Unicode input mode to EEPROM |
+|`UNICODE_TYPE_DELAY` |`10` |The amount of time to wait, in milliseconds, between Unicode sequence keystrokes|
+
+### Audio Feedback :id=audio-feedback
-
+If you have the [Audio](feature_audio.md) feature enabled on your board, you can configure it to play sounds when the input mode is changed.
-### 1.1. Basic Unicode :id=basic-unicode
+Add the following to your `config.h`:
-The easiest to use method, albeit somewhat limited. It stores Unicode characters as keycodes in the keymap itself, so it only supports code points up to `0x7FFF`. This covers characters for most modern languages (including East Asian), as well as symbols, but it doesn't cover emoji.
+|Define |Default|Description |
+|-------------------|-------|-----------------------------------------------------------|
+|`UNICODE_SONG_MAC` |*n/a* |The song to play when the macOS input mode is selected |
+|`UNICODE_SONG_LNX` |*n/a* |The song to play when the Linux input mode is selected |
+|`UNICODE_SONG_BSD` |*n/a* |The song to play when the BSD input mode is selected |
+|`UNICODE_SONG_WIN` |*n/a* |The song to play when the Windows input mode is selected |
+|`UNICODE_SONG_WINC`|*n/a* |The song to play when the WinCompose input mode is selected|
-Add the following to your `rules.mk`:
+## Input Subsystems :id=input-subsystems
+
+Each of these subsystems have their own pros and cons in terms of flexibility and ease of use. Choose the one that best fits your needs.
+
+
+
+### ** Basic **
+
+This is the easiest to use, albeit somewhat limited. It supports code points up to `U+7FFF`, which covers characters for most modern languages (including East Asian), as well as many symbols, but does not include emoji.
+
+To enable Basic Unicode, add the following to your `rules.mk`:
```make
UNICODE_ENABLE = yes
```
-Then add `UC(c)` keycodes to your keymap, where _c_ is the code point of the desired character (preferably in hexadecimal, up to 4 digits long). For example, `UC(0x40B)` will output [Ћ](https://unicode-table.com/en/040B/), and `UC(0x30C4)` will output [ツ](https://unicode-table.com/en/30C4).
-
-
+You can then add `UC(c)` keycodes to your keymap, where *c* is the code point of the desired character (in hexadecimal - the `U+` prefix will not work). For example, `UC(0x40B)` will output [Ћ](https://unicode-table.com/en/040B/), and `UC(0x30C4)` will output [ツ](https://unicode-table.com/en/30C4).
-### 1.2. Unicode Map :id=unicode-map
+### ** Unicode Map **
-In addition to standard character ranges, this method also covers emoji, ancient scripts, rare symbols etc. In fact, all possible code points (up to `0x10FFFF`) are supported. Here, Unicode characters are stored in a separate mapping table. You need to maintain a `unicode_map` array in your keymap file, which may contain at most 16384 entries.
+Unicode Map supports all possible code points (up to `U+10FFFF`). Here, the code points are stored in a separate mapping table (which may contain at most 16,384 entries), instead of directly in the keymap.
-Add the following to your `rules.mk`:
+To enable Unicode Map, add the following to your `rules.mk`:
```make
UNICODEMAP_ENABLE = yes
```
-Then add `X(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name.
+Then, you will need to create a mapping table in your `keymap.c`, and (optionally) an enum for naming the array indices, like so:
```c
enum unicode_names {
@@ -51,242 +80,373 @@ enum unicode_names {
SNEK
};
-const uint32_t unicode_map[] PROGMEM = {
+const uint32_t PROGMEM unicode_map[] = {
[BANG] = 0x203D, // ‽
[IRONY] = 0x2E2E, // ⸮
[SNEK] = 0x1F40D, // 🐍
};
```
-Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
+Finally, add `UM(i)` keycodes to your keymap, where *i* is an index into the `unicode_map[]` array. If you defined the enum above, you can use those names instead, for example `UM(BANG)` or `UM(SNEK)`.
-#### Lower and Upper Case
+#### Lower and Upper Case Pairs :id=unicodemap-pairs
-Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
+Some writing systems have lowercase and uppercase variants of each character, such as å and Å. To make inputting these characters easier, you can use the `UP(i, j)` keycode in your keymap, where *i* and *j* are the mapping table indices of the lowercase and uppercase characters, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the uppercase character will be inserted; otherwise, the lowercase character will be inserted.
-This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP()`. This helps blend Unicode keys in with regular alphas.
+```c
+const uint32_t PROGMEM unicode_map[] = {
+ [AE_LOWER] = 0x00E6, // æ
+ [AE_UPPER] = 0x00C6, // Æ
+};
+```
-Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L36) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
+This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key. This helps blend Unicode keys in with regular keycodes.
-
+Due to keycode size constraints, *i* and *j* can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ *i* ≤ 127 and 0 ≤ *j* ≤ 127.
-### 1.3. UCIS :id=ucis
+### ** UCIS **
-This method also supports all possible code points. As with the Unicode Map method, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature — you have to create a custom keycode or function that invokes this functionality.
+As with Unicode Map, the UCIS method also supports all possible code points, and requires the use of a mapping table. However, it works much differently - Unicode characters are input by replacing a typed mnemonic.
-Add the following to your `rules.mk`:
+To enable UCIS, add the following to your keymap's `rules.mk`:
```make
UCIS_ENABLE = yes
```
-Then define a table like this in your keymap file:
+Then, create a mapping table in your `keymap.c`:
```c
const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
UCIS_SYM("poop", 0x1F4A9), // 💩
UCIS_SYM("rofl", 0x1F923), // 🤣
- UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺
+ UCIS_SYM("ukr", 0x1F1FA, 0x1F1E6), // 🇺🇦
UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0) // ಠ_ಠ
);
```
-By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file.
+By default, each table entry may be up to three code points long. This can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your keymap's `config.h`.
-To use UCIS input, call `ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
+To invoke UCIS input, the `ucis_start()` function must first be called (for example, in a custom "Unicode" keycode). Then, type the mnemonic for the mapping table entry (such as "rofl"), and hit Space or Enter. The "rofl" text will be backspaced and the emoji inserted.
-#### Customization
+
-There are several functions that you can define in your keymap to customize the functionality of this feature.
+## Input Modes :id=input-modes
-* `void ucis_start_user(void)` – This runs when you call the "start" function, and can be used to provide feedback. By default, it types out a keyboard emoji.
-* `void ucis_success(uint8_t symbol_index)` – This runs when the input has matched something and has completed. By default, it doesn't do anything.
-* `void ucis_symbol_fallback (void)` – This runs when the input doesn't match anything. By default, it falls back to trying that input as a Unicode code.
+Unicode input works by typing a sequence of characters, similar to a macro. However, since this sequence depends on your OS, you will need to prepare both your host machine and QMK to recognise and send the correct Unicode input sequences respectively.
-You can find the default implementations of these functions in [`process_ucis.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c).
+To set the list of enabled input modes, add the `UNICODE_SELECTED_MODES` define to your keymap's `config.h`, for example:
+```c
+#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
+// or
+#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_WINCOMPOSE
+```
-## 2. Input Modes :id=input-modes
+These modes can then be cycled through using the `UC_NEXT` and `UC_PREV` keycodes. You can also switch to any input mode, even if it is not specified in `UNICODE_SELECTED_MODES`, using their respective keycodes.
-Unicode input in QMK works by inputting a sequence of characters to the OS, sort of like a macro. Unfortunately, the way this is done differs for each platform. Specifically, each platform requires a different combination of keys to trigger Unicode input. Therefore, a corresponding input mode has to be set in QMK.
+If your keyboard has working EEPROM, it will remember the last used input mode and continue using it on the next power up. This can be disabled by defining `UNICODE_CYCLE_PERSIST` to `false`.
-The following input modes are available:
+
-* **`UNICODE_MODE_MACOS`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).
+### ** macOS **
- To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.
- By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with a different keycode.
+**Mode Name:** `UNICODE_MODE_MACOS`
- !> Using the _Unicode Hex Input_ input source may disable some Option-based shortcuts, such as Option+Left and Option+Right.
+macOS has built-in support for Unicode input as its own input source. It supports all possible code points by way of surrogate pairs for code points above `U+FFFF`.
-* **`UNICODE_MODE_LINUX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points).
+To enable, go to **System Preferences → Keyboard → Input Sources**, then add Unicode Hex Input to the list (under Other), and activate it from the input dropdown in the menu bar. Note that this may disable some Option-based shortcuts such as Option+Left and Option+Right.
- Enabled by default and works almost anywhere on IBus-enabled distros. Without IBus, this mode works under GTK apps, but rarely anywhere else.
- By default, this mode uses Ctrl+Shift+U (`LCTL(LSFT(KC_U))`) to start Unicode input, but this can be changed by defining [`UNICODE_KEY_LNX`](#input-key-configuration) with a different keycode. This might be required for IBus versions ≥1.5.15, where Ctrl+Shift+U behavior is consolidated into Ctrl+Shift+E.
+### ** Linux (IBus) **
- Users who wish support in non-GTK apps without IBus may need to resort to a more indirect method, such as creating a custom keyboard layout ([more on this method](#custom-linux-layout)).
+**Mode Name:** `UNICODE_MODE_LINUX`
-* **`UNICODE_MODE_WINDOWS`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`.
+For Linux distros with IBus, Unicode input is enabled by default, supports all possible code points, and works almost anywhere. Without IBus, it works under GTK apps, but rarely anywhere else.
- To enable, create a registry key under `HKEY_CURRENT_USER\Control Panel\Input Method` of type `REG_SZ` called `EnableHexNumpad` and set its value to `1`. This can be done from the Command Prompt by running `reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1` with administrator privileges. Reboot afterwards.
- This mode is not recommended because of reliability and compatibility issues; use the `UNICODE_MODE_WINCOMPOSE` mode instead.
+Users who would like support in non-GTK apps without IBus may need to resort to a more indirect method, such as creating a custom keyboard layout.
-* **`UNICODE_MODE_BSD`**: _(non implemented)_ Unicode input under BSD. Not implemented at this time. If you're a BSD user and want to help add support for it, please [open an issue on GitHub](https://github.com/qmk/qmk_firmware/issues).
+### ** Windows (WinCompose) **
-* **`UNICODE_MODE_WINCOMPOSE`**: Windows Unicode input using [WinCompose](https://github.com/samhocevar/wincompose). As of v0.9.0, supports code points up to `0x10FFFF` (all possible code points).
+**Mode Name:** `UNICODE_MODE_WINCOMPOSE`
- To enable, install the [latest release](https://github.com/samhocevar/wincompose/releases/latest). Once installed, WinCompose will automatically run on startup. This mode works reliably under all version of Windows supported by the app.
- By default, this mode uses right Alt (`KC_RALT`) as the Compose key, but this can be changed in the WinCompose settings and by defining [`UNICODE_KEY_WINC`](#input-key-configuration) with a different keycode.
+This mode requires a third-party tool called [WinCompose](https://github.com/samhocevar/wincompose). It supports all possible code points, and is the recommended input mode for Windows.
+To enable, install the [latest release from GitHub](https://github.com/samhocevar/wincompose/releases/latest). Once installed, it will automatically run on startup. This works reliably under all versions of Windows supported by WinCompose.
-## 3. Setting the Input Mode :id=setting-the-input-mode
+### ** Windows (HexNumpad) **
-To set your desired input mode, add the following define to your `config.h`:
+**Mode Name:** `UNICODE_MODE_WINDOWS`
-```c
-#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
-```
+!> This input mode is *not* the "Alt code" system. Alt codes are not Unicode; they instead follow [the Windows-1252 character set](https://en.wikipedia.org/wiki/Alt_code).
-This example sets the board's default input mode to `UNICODE_MODE_LINUX`. You can replace this with `UNICODE_MODE_MACOS`, `UNICODE_MODE_WINCOMPOSE`, or any of the other modes listed [above](#input-modes). The board will automatically use the selected mode on startup, unless you manually switch to another mode (see [below](#keycodes)).
+This is Windows' built-in hex numpad Unicode input mode. It only supports code points up to `U+FFFF`, and is not recommended due to reliability and compatibility issues.
-You can also select multiple input modes, which allows you to easily cycle through them using the `UC_NEXT`/`UC_PREV` keycodes.
+To enable, run the following as an administrator, then reboot:
-```c
-#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_LINUX, UNICODE_MODE_WINCOMPOSE
+```
+reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1
```
-Note that the values are separated by commas. The board will remember the last used input mode and will continue using it on next power-up. You can disable this and force it to always start with the first mode in the list by adding `#define UNICODE_CYCLE_PERSIST false` to your `config.h`.
+### ** Emacs **
-#### Keycodes
+**Mode Name:** `UNICODE_MODE_EMACS`
-You can switch the input mode at any time by using the following keycodes. Adding these to your keymap allows you to quickly switch to a specific input mode, including modes not listed in `UNICODE_SELECTED_MODES`.
+Emacs supports code point input with the `insert-char` command.
-|Keycode |Alias |Input Mode |Description |
-|----------------------------|---------|-------------------------|-----------------------------------------------------------------------------|
-|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Next in list |Cycle through selected modes, reverse direction when Shift is held |
-|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Prev in list |Cycle through selected modes in reverse, forward direction when Shift is held|
-|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |`UNICODE_MODE_MACOS` |Switch to macOS input |
-|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|`UNICODE_MODE_LINUX` |Switch to Linux input |
-|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |`UNICODE_MODE_WINDOWS` |Switch to Windows input |
-|`QK_UNICODE_MODE_BSD` |`UC_BSD` |`UNICODE_MODE_BSD` |Switch to BSD input _(not implemented)_ |
-|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|`UNICODE_MODE_WINCOMPOSE`|Switch to Windows input using WinCompose |
-|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|`UNICODE_MODE_EMACS` |Switch to emacs (`C-x-8 RET`) |
+### ** BSD **
-You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UNICODE_MODE_LINUX`).
+**Mode Name:** `UNICODE_MODE_BSD`
-?> Using `UNICODE_SELECTED_MODES` is preferable to calling `set_unicode_input_mode()` in `matrix_init_user()` or similar functions, since it's better integrated into the Unicode system and has the added benefit of avoiding unnecessary writes to EEPROM.
+Not currently implemented. If you're a BSD user and want to contribute support for this input mode, please [feel free](contributing.md)!
-#### Audio Feedback
+
-If you have the [Audio feature](feature_audio.md) enabled on the board, you can set melodies to be played when you press the above keys. That way you can have some audio feedback when switching input modes.
+## Keycodes :id=keycodes
-For instance, you can add these definitions to your `config.h` file:
+|Key |Aliases |Description |
+|----------------------------|---------|----------------------------------------------------------------|
+|`UC(c)` | |Send Unicode code point `c`, up to `0x7FFF` |
+|`UM(i)` | |Send Unicode code point at index `i` in `unicode_map` |
+|`UP(i, j)` | |Send Unicode code point at index `i`, or `j` if Shift/Caps is on|
+|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Cycle through selected input modes |
+|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Cycle through selected input modes in reverse |
+|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |Switch to macOS input |
+|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|Switch to Linux input |
+|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |Switch to Windows input |
+|`QK_UNICODE_MODE_BSD` |`UC_BSD` |Switch to BSD input (not implemented) |
+|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|Switch to Windows input using WinCompose |
+|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|Switch to emacs (`C-x-8 RET`) |
-```c
-#define UNICODE_SONG_MAC AUDIO_ON_SOUND
-#define UNICODE_SONG_LNX UNICODE_LINUX
-#define UNICODE_SONG_BSD TERMINAL_SOUND
-#define UNICODE_SONG_WIN UNICODE_WINDOWS
-#define UNICODE_SONG_WINC UNICODE_WINDOWS
-```
+## API :id=api
+### `uint8_t get_unicode_input_mode(void)` :id=api-get-unicode-input-mode
-## Additional Customization
+Get the current Unicode input mode.
-Because Unicode is a large and versatile feature, there are a number of options you can customize to make it work better on your system.
+#### Return Value :id=api-get-unicode-input-mode-return-value
-### Start and Finish Input Functions
+The currently active Unicode input mode.
-The functions for starting and finishing Unicode input on your platform can be overridden locally. Possible uses include customizing input mode behavior if you don't use the default keys, or adding extra visual/audio feedback to Unicode input.
+---
-* `void unicode_input_start(void)` – This sends the initial sequence that tells your platform to enter Unicode input mode. For example, it holds the left Alt key followed by Num+ on Windows, and presses the `UNICODE_KEY_LNX` combination (default: Ctrl+Shift+U) on Linux.
-* `void unicode_input_finish(void)` – This is called to exit Unicode input mode, for example by pressing Space or releasing the Alt key.
+### `void set_unicode_input_mode(uint8_t mode)` :id=api-set-unicode-input-mode
-You can find the default implementations of these functions in [`process_unicode_common.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode_common.c).
+Set the Unicode input mode.
-### Input Mode Callbacks
+#### Arguments :id=api-set-unicode-input-mode-arguments
-There are callbacks functions available that are called whenever the unicode input mode changes. The new input mode is passed to the function.
+ - `uint8_t mode`
+ The input mode to set.
-|Callback |Description |
-|---------------------------------------------------|-----------------------------------------------------|
-| `unicode_input_mode_set_kb(uint8_t input_mode)` | Callback for unicode input mode set, for keyboard. |
-| `unicode_input_mode_set_user(uint8_t input_mode)` | Callback for unicode input mode set, for users. |
+---
-This feature can be used, for instance, to implement LED indicators for the current unicode input mode.
+### `void unicode_input_mode_step(void)` : id=api-unicode-input-mode-step
-### Input Key Configuration
+Change to the next Unicode input mode.
-You can customize the keys used to trigger Unicode input for macOS, Linux and WinCompose by adding corresponding defines to your `config.h`. The default values match the platforms' default settings, so you shouldn't need to change this unless Unicode input isn't working, or you want to use a different key (e.g. in order to free up left or right Alt).
+---
-|Define |Type |Default |Example |
-|------------------|----------|------------------|-------------------------------------------|
-|`UNICODE_KEY_MAC` |`uint8_t` |`KC_LALT` |`#define UNICODE_KEY_MAC KC_RALT` |
-|`UNICODE_KEY_LNX` |`uint16_t`|`LCTL(LSFT(KC_U))`|`#define UNICODE_KEY_LNX LCTL(LSFT(KC_E))`|
-|`UNICODE_KEY_WINC`|`uint8_t` |`KC_RALT` |`#define UNICODE_KEY_WINC KC_RGUI` |
+### `void unicode_input_mode_step_reverse(void)` : id=api-unicode-input-mode-step-reverse
+Change to the previous Unicode input mode.
-## Sending Unicode Strings
+---
-QMK provides several functions that allow you to send Unicode input to the host programmatically:
+### `void unicode_input_mode_set_user(uint8_t input_mode)` :id=api-unicode-input-mode-set-user
-### `send_unicode_string()`
+User-level callback, invoked when the input mode is changed.
-This function is much like `send_string()`, but it allows you to input UTF-8 characters directly. It supports all code points, provided the selected input mode also supports it. Make sure your `keymap.c` file is formatted using UTF-8 encoding.
+#### Arguments :id=api-unicode-input-mode-set-user-arguments
-```c
-send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");
-```
+ - `uint8_t input_mode`
+ The new input mode.
-Example uses include sending Unicode strings when a key is pressed, as described in [Macros](feature_macros.md).
+---
-## Additional Language Support
+### `void unicode_input_mode_set_kb(uint8_t input_mode)` :id=api-unicode-input-mode-set-kb
-In `quantum/keymap_extras`, you'll see various language files — these work the same way as the ones for alternative layouts such as Colemak or BÉPO. When you include one of these language headers, you gain access to keycodes specific to that language / national layout. Such keycodes are defined by a 2-letter country/language code, followed by an underscore and a 4-letter abbreviation of the character to which the key corresponds. For example, including `keymap_french.h` and using `FR_UGRV` in your keymap will output `ù` when typed on a system with a native French AZERTY layout.
+Keyboard-level callback, invoked when the input mode is changed.
-If the primary system layout you use on your machine is different from US ANSI, using these language-specific keycodes can help your QMK keymaps better match what will actually be output on the screen. However, keep in mind that these keycodes are just aliases for the corresponding default US keycodes under the hood, and that the HID protocol used by keyboards is itself inherently based on US ANSI.
+#### Arguments :id=api-unicode-input-mode-set-kb-arguments
+ - `uint8_t input_mode`
+ The new input mode.
-## International Characters on Windows
+---
-### AutoHotkey
+### `void unicode_input_start(void)` :id=api-unicode-input-start
-The method does not require Unicode support in the keyboard itself but instead depends on [AutoHotkey](https://autohotkey.com) running in the background.
+Begin the Unicode input sequence. The exact behavior depends on the currently selected input mode:
-First you need to select a modifier combination that is not in use by any of your programs.
-Ctrl+Alt+Win is not used very widely and should therefore be perfect for this.
-There is a macro defined for a mod-tab combo `LCAG_T`.
-Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`.
-This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key.
+ - **macOS**: Hold `UNICODE_KEY_MAC`
+ - **Linux**: Tap `UNICODE_KEY_LNX`
+ - **WinCompose**: Tap `UNICODE_KEY_WINC`, then U
+ - **HexNumpad**: Hold Left Alt, then tap Numpad +
+ - **Emacs**: Tap Ctrl+X, then 8, then Enter
-In the default script of AutoHotkey you can define custom hotkeys.
+This function is weakly defined, and can be overridden in user code.
- <^ { [ r, R, U1F923 ] };
-```
+ - **macOS**: Release `UNICODE_KEY_MAC`
+ - **Linux**: Tap Escape
+ - **WinCompose**: Tap Escape
+ - **HexNumpad**: Release Left Alt
+ - **Emacs**: Tap Ctrl+G
+
+This function is weakly defined, and can be overridden in user code.
+
+---
+
+### `void register_unicode(uint32_t code_point)` :id=api-register-unicode
+
+Input a single Unicode character. A surrogate pair will be sent if required by the input mode.
+
+#### Arguments :id=api-register-unicode-arguments
+
+ - `uint32_t code_point`
+ The code point of the character to send.
+
+---
+
+### `void send_unicode_string(const char *str)` :id=api-send-unicode-string
+
+Send a string containing Unicode characters.
+
+#### Arguments :id=api-send-unicode-string-arguments
+
+ - `const char *str`
+ The string to send.
+
+---
+
+### `uint8_t unicodemap_index(uint16_t keycode)` :id=api-unicodemap-index
+
+Get the index into the `unicode_map` array for the given keycode, respecting shift state for pair keycodes.
+
+#### Arguments :id=api-unicodemap-index-arguments
+
+ - `uint16_t keycode`
+ The Unicode Map keycode to get the index of.
+
+#### Return Value :id=api-unicodemap-index-return-value
+
+An index into the `unicode_map` array.
+
+---
+
+### `uint32_t unicodemap_get_code_point(uint8_t index)` :id=api-unicodemap-get-code-point
+
+Get the code point for the given index in the `unicode_map` array.
+
+#### Arguments :id=unicodemap-get-code-point-arguments
+
+ - `uint8_t index`
+ The index into the `unicode_map` array.
+
+#### Return Value :id=unicodemap-get-code-point-return-value
+
+A Unicode code point value.
+
+---
+
+### `void register_unicodemap(uint8_t index)` :id=api-register-unicodemap
+
+Send the code point for the given index in the `unicode_map` array.
+
+#### Arguments :id=api-register-unicodemap-arguments
+
+ - `uint8_t index`
+ The index into the `unicode_map` array.
+
+---
+
+### `void ucis_start(void)` :id=api-ucis-start
+
+Begin the input sequence.
+
+---
+
+### `bool ucis_active(void)` :id=api-ucis-active
+
+Whether UCIS is currently active.
+
+#### Return Value :id=api-ucis-active-return-value
+
+`true` if UCIS is active.
+
+---
+
+### `uint8_t ucis_count(void)` :id=api-ucis-count
+
+Get the number of characters in the input sequence buffer.
+
+#### Return Value :id=api-ucis-count-return-value
+
+The current input sequence buffer length.
+
+---
+
+### `bool ucis_add(uint16_t keycode)` :id=api-ucis-add
+
+Add the given keycode to the input sequence buffer.
+
+#### Arguments :id=api-ucis-add-arguments
+
+ - `uint16_t keycode`
+ The keycode to add. Must be between `KC_A` and `KC_Z`, or `KC_1` and `KC_0`.
+
+#### Return Value :id=api-ucis-add-return-value
+
+`true` if the keycode was added.
+
+---
+
+### `bool ucis_remove_last(void)` :id=api-ucis-remove-last
+
+Remove the last character from the input sequence buffer.
+
+#### Return Value :id=api-ucis-remove-last
+
+`true` if the sequence was not empty.
+
+---
+
+### `void ucis_finish(void)` :id=api-ucis-finish
+
+Mark the input sequence as complete, and attempt to match.
+
+---
+
+### `void ucis_cancel(void)` :id=api-ucis-cancel
+
+Cancel the input sequence.
+
+---
+
+### `void register_ucis(void)` :id=api-register-ucis
-Save the file and run the command `setxkbmap us` to reload the layout.
+Send the code point(s) for the given UCIS index.
-You can define one custom character for key defined in the layout, and another if you populate the fourth layer. Additional layers up to 8th are also possible.
+#### Arguments :id=api-register-ucis-arguments
-This method is specific to the computer on which you set the custom layout. The custom keys will be available only when Xorg is running. To avoid accidents, you should always reload the layout using `setxkbmap`, otherwise an invalid layout could prevent you from logging into your system, locking you out.
+ - `uint8_t index`
+ The index into the UCIS symbol table.
diff --git a/docs/feature_userspace.md b/docs/feature_userspace.md
index 8c617fe33a06..aabf18e393ee 100644
--- a/docs/feature_userspace.md
+++ b/docs/feature_userspace.md
@@ -1,5 +1,7 @@
# Userspace: Sharing Code Between Keymaps
+!> Please note, userspace submissions to the upstream `qmk/qmk_firmware` repository are no longer being accepted. The userspace feature itself remains functional and can be configured locally.
+
If you use more than one keyboard with a similar keymap, you might see the benefit in being able to share code between them. Create your own folder in `users/` named the same as your keymap (ideally your GitHub username, ``) with the following structure:
* `/users//` (added to the path automatically)
diff --git a/docs/feature_velocikey.md b/docs/feature_velocikey.md
deleted file mode 100644
index aeb1865e8aff..000000000000
--- a/docs/feature_velocikey.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Velocikey
-
-Velocikey is a feature that lets you control the speed of lighting effects (like the Rainbow Swirl effect) with the speed of your typing. The faster you type, the faster the lights will go!
-
-## Usage
-For Velocikey to take effect, there are two steps. First, when compiling your keyboard, you'll need to set `VELOCIKEY_ENABLE=yes` in `rules.mk`, e.g.:
-
-```
-MOUSEKEY_ENABLE = no
-STENO_ENABLE = no
-EXTRAKEY_ENABLE = yes
-VELOCIKEY_ENABLE = yes
-```
-
-Then, while using your keyboard, you need to also turn it on with the `VK_TOGG` keycode, which toggles the feature on and off.
-
-The following light effects will all be controlled by Velocikey when it is enabled:
- - RGB Breathing
- - RGB Rainbow Mood
- - RGB Rainbow Swirl
- - RGB Snake
- - RGB Knight
-
-Support for LED breathing effects is planned but not available yet.
-
- As long as Velocikey is enabled, it will control the speed regardless of any other speed setting that your RGB lights are currently on.
-
- ## Configuration
- Velocikey doesn't currently support any configuration via keyboard settings. If you want to adjust something like the speed increase or decay rate, you would need to edit `velocikey.c` and adjust the values there to achieve the kinds of speeds that you like.
diff --git a/docs/flashing.md b/docs/flashing.md
index 443fa3123e1b..113d90ca38ff 100644
--- a/docs/flashing.md
+++ b/docs/flashing.md
@@ -322,6 +322,29 @@ Flashing sequence:
3. Flash a .bin file
4. Reset the device into application mode (may be done automatically)
+## WB32 DFU
+
+Some keyboards produced for several commercial brands (GMMK, Akko, MonsGeek, Inland) use this bootloader. The `wb32-dfu-updater` utility is bundled with [QMK MSYS](https://msys.qmk.fm/) and [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide). If neither of these flashing methods is available for your OS, you will likely need to [compile the CLI version from source](https://github.com/WestberryTech/wb32-dfu-updater).
+
+The `info.json` setting for this bootloader is `wb32-dfu`.
+
+Compatible flashers:
+
+* [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide) (recommended GUI)
+* [wb32-dfu-updater_cli](https://github.com/WestberryTech/wb32-dfu-updater) / `:flash` target in QMK (recommended command line)
+ ```
+ wb32-dfu-updater_cli -t -s 0x8000000 -D
+ ```
+
+Flashing sequence:
+
+1. Enter the bootloader using any of the following methods:
+ * Tap the `QK_BOOT` keycode
+ * Press the `RESET` button on the PCB
+2. Wait for the OS to detect the device
+3. Flash a .bin file
+4. Reset the device into application mode (may be done automatically)
+
## tinyuf2
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.
diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md
index 1a7e276098a7..3d98e4602b48 100644
--- a/docs/getting_started_make_guide.md
+++ b/docs/getting_started_make_guide.md
@@ -109,7 +109,7 @@ This allows you to send Unicode characters using `UC()` in your keym
`UNICODEMAP_ENABLE`
-This allows you to send Unicode characters using `X(