Merge qmk/develop

This commit is contained in:
elpekenin 2024-02-17 11:24:42 +01:00
commit 7392b62e97
17211 changed files with 295293 additions and 622729 deletions

4
.github/labeler.yml vendored
View File

@ -40,3 +40,7 @@ translation:
- docs/ru-ru/**/* - docs/ru-ru/**/*
CI: CI:
- .github/**/* - .github/**/*
dd:
- data/constants/**/*
- data/mappings/**/*
- data/schemas/**/*

View File

@ -25,7 +25,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
persist-credentials: false persist-credentials: false

View File

@ -27,7 +27,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@ -33,7 +33,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
ref: ${{ github.event.inputs.branch || github.ref }} ref: ${{ github.event.inputs.branch || github.ref }}
@ -53,7 +53,7 @@ jobs:
[ ! -f .failed ] || exit 1 [ ! -f .failed ] || exit 1
- name: 'Upload artifacts' - name: 'Upload artifacts'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
name: artifacts-${{ github.event.inputs.branch || github.ref_name }}-${{ matrix.keymap }} name: artifacts-${{ github.event.inputs.branch || github.ref_name }}-${{ matrix.keymap }}

View File

@ -24,7 +24,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive

View File

@ -15,7 +15,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
token: ${{ secrets.QMK_BOT_TOKEN }} token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0 fetch-depth: 0

View File

@ -23,7 +23,7 @@ jobs:
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
@ -37,7 +37,7 @@ jobs:
qmk --verbose generate-docs qmk --verbose generate-docs
- name: Deploy - name: Deploy
uses: JamesIves/github-pages-deploy-action@v4.4.2 uses: JamesIves/github-pages-deploy-action@v4.5.0
with: with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_BRANCH: master BASE_BRANCH: master

View File

@ -18,9 +18,10 @@ jobs:
matrix: matrix:
branch: branch:
- xap - xap
- riot
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
token: ${{ secrets.QMK_BOT_TOKEN }} token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0 fetch-depth: 0

View File

@ -25,7 +25,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
@ -35,7 +35,7 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v36 uses: tj-actions/changed-files@v42
- name: Run qmk formatters - name: Run qmk formatters
shell: 'bash {0}' shell: 'bash {0}'

View File

@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@ -12,7 +12,7 @@ jobs:
triage: triage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/labeler@main - uses: actions/labeler@v4
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: '.github/labeler.yml' configuration-path: '.github/labeler.yml'

View File

@ -18,7 +18,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
@ -27,7 +27,7 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v36 uses: tj-actions/changed-files@v42
- name: Print info - name: Print info
run: | run: |
@ -36,6 +36,7 @@ jobs:
echo '${{ steps.file_changes.outputs.all_changed_files}}' echo '${{ steps.file_changes.outputs.all_changed_files}}'
- name: Run qmk lint - name: Run qmk lint
if: always()
shell: 'bash {0}' shell: 'bash {0}'
run: | run: |
QMK_CHANGES=$(echo -e '${{ steps.file_changes.outputs.all_changed_files}}' | sed 's/ /\n/g') QMK_CHANGES=$(echo -e '${{ steps.file_changes.outputs.all_changed_files}}' | sed 's/ /\n/g')
@ -72,3 +73,11 @@ jobs:
exit 255 exit 255
fi fi
exit $exit_code exit $exit_code
- name: Verify keyboard aliases
if: always()
shell: 'bash {0}'
run: |
git reset --hard
git clean -xfd
qmk ci-validate-aliases

View File

@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Run qmk generators - name: Run qmk generators
run: | run: |

View File

@ -19,7 +19,7 @@ jobs:
- name: Disable safe.directory check - name: Disable safe.directory check
run : git config --global --add safe.directory '*' run : git config --global --add safe.directory '*'
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Run qmk generators - name: Run qmk generators
run: | run: |

View File

@ -3,6 +3,7 @@ name: 'Close stale issues and PRs'
permissions: permissions:
issues: write issues: write
pull-requests: write pull-requests: write
actions: write
on: on:
schedule: schedule:
@ -13,7 +14,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v8 - uses: actions/stale@main
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -26,7 +26,7 @@ jobs:
container: ghcr.io/qmk/qmk_cli container: ghcr.io/qmk/qmk_cli
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Install dependencies - name: Install dependencies

9
.gitignore vendored
View File

@ -18,6 +18,11 @@
*.lst *.lst
*.map *.map
*.o *.o
*.a
*.so
*.dylib
*.dll
*.la
*.stackdump *.stackdump
*.sym *.sym
@ -95,6 +100,7 @@ secrets.tar
# Python things # Python things
__pycache__ __pycache__
.python-version .python-version
.venv
# Prerequisites for updating ChibiOS # Prerequisites for updating ChibiOS
/util/fmpp* /util/fmpp*
@ -107,5 +113,6 @@ compile_commands.json
.clangd/ .clangd/
.cache/ .cache/
# VIA(L) json files that don't belong in QMK repo # VIA(L) files that don't belong in QMK repo
via*.json via*.json
/keyboards/**/keymaps/vial/*

View File

@ -38,6 +38,11 @@ $(info QMK Firmware $(QMK_VERSION))
endif endif
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 # Determine which qmk cli to use
QMK_BIN := qmk 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_4)/keymaps/*/.)))
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/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) KEYBOARD_LAYOUTS := $(shell $(QMK_BIN) list-layouts --keyboard $1)
LAYOUT_KEYMAPS := LAYOUT_KEYMAPS :=
$$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/layouts/*/$$(LAYOUT)/*/.))))) $$(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)) KEYMAPS := $$(sort $$(KEYMAPS) $$(LAYOUT_KEYMAPS))
@ -300,17 +316,18 @@ endef
define BUILD_TEST define BUILD_TEST
TEST_PATH := $1 TEST_PATH := $1
TEST_NAME := $$(notdir $$(TEST_PATH)) TEST_NAME := $$(notdir $$(TEST_PATH))
TEST_FULL_NAME := $$(subst /,_,$$(patsubst $$(ROOT_DIR)tests/%,%,$$(TEST_PATH)))
MAKE_TARGET := $2 MAKE_TARGET := $2
COMMAND := $1 COMMAND := $1
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET) 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) MAKE_MSG := $$(MSG_MAKE_TEST)
$$(eval $$(call BUILD)) $$(eval $$(call BUILD))
ifneq ($$(MAKE_TARGET),clean) ifneq ($$(MAKE_TARGET),clean)
TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_FULL_NAME).elf
TESTS += $$(TEST_NAME) TESTS += $$(TEST_FULL_NAME)
TEST_MSG := $$(MSG_TEST) TEST_MSG := $$(MSG_TEST)
$$(TEST_NAME)_COMMAND := \ $$(TEST_FULL_NAME)_COMMAND := \
printf "$$(TEST_MSG)\n"; \ printf "$$(TEST_MSG)\n"; \
$$(TEST_EXECUTABLE); \ $$(TEST_EXECUTABLE); \
if [ $$$$? -gt 0 ]; \ if [ $$$$? -gt 0 ]; \
@ -320,6 +337,12 @@ define BUILD_TEST
endif endif
endef endef
define LIST_TEST
include $(BUILDDEFS_PATH)/testlist.mk
FOUND_TESTS := $$(patsubst ./tests/%,%,$$(TEST_LIST))
$$(info $$(FOUND_TESTS))
endef
define PARSE_TEST define PARSE_TEST
TESTS := TESTS :=
TEST_NAME := $$(firstword $$(subst :, ,$$(RULE))) TEST_NAME := $$(firstword $$(subst :, ,$$(RULE)))
@ -328,7 +351,7 @@ define PARSE_TEST
ifeq ($$(TEST_NAME),all) ifeq ($$(TEST_NAME),all)
MATCHED_TESTS := $$(TEST_LIST) MATCHED_TESTS := $$(TEST_LIST)
else else
MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),)) MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring x$$(TEST_NAME)x, x$$(patsubst ./tests/%,%,$$(TEST)x)), $$(TEST),))
endif endif
$$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET)))) $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
endef endef
@ -413,6 +436,10 @@ git-submodules: git-submodule
list-keyboards: list-keyboards:
$(QMK_BIN) list-keyboards --no-resolve-defaults | tr '\n' ' ' $(QMK_BIN) list-keyboards --no-resolve-defaults | tr '\n' ' '
.PHONY: list-tests
list-tests:
$(eval $(call LIST_TEST))
.PHONY: generate-keyboards-file .PHONY: generate-keyboards-file
generate-keyboards-file: generate-keyboards-file:
$(QMK_BIN) list-keyboards --no-resolve-defaults $(QMK_BIN) list-keyboards --no-resolve-defaults
@ -423,8 +450,18 @@ clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
echo 'done.' echo 'done.'
.PHONY: distclean .PHONY: distclean distclean_qmk
distclean: clean distclean: distclean_qmk
distclean_qmk: clean
echo -n 'Deleting *.bin, *.hex, and *.uf2 ... ' echo -n 'Deleting *.bin, *.hex, and *.uf2 ... '
rm -f *.bin *.hex *.uf2 rm -f *.bin *.hex *.uf2
echo 'done.' 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

View File

@ -13,11 +13,10 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
$(TEST)_INC := \ $(TEST_OUTPUT)_INC := \
tests/test_common/common_config.h tests/test_common/common_config.h
$(TEST)_SRC := \ $(TEST_OUTPUT)_SRC := \
$(TMK_COMMON_SRC) \
$(QUANTUM_SRC) \ $(QUANTUM_SRC) \
$(SRC) \ $(SRC) \
$(QUANTUM_PATH)/keymap_introspection.c \ $(QUANTUM_PATH)/keymap_introspection.c \
@ -31,8 +30,8 @@ $(TEST)_SRC := \
tests/test_common/test_logger.cpp \ tests/test_common/test_logger.cpp \
$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.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 VPATH += $(TOP_DIR)/tests/test_common

View File

@ -1,17 +1,36 @@
# Look for a json keymap file # Look for a json keymap file
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","") ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","")
KEYMAP_JSON := $(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)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","")
KEYMAP_JSON := $(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)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","")
KEYMAP_JSON := $(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)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","")
KEYMAP_JSON := $(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)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
KEYMAP_JSON := $(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 endif

View File

@ -27,7 +27,6 @@ QMK_BIN ?= qmk
# Set the filename for the final firmware binary # Set the filename for the final firmware binary
KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD)) KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD))
TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP) TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP)
KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
ifeq ($(strip $(DUMP_CI_METADATA)),yes) ifeq ($(strip $(DUMP_CI_METADATA)),yes)
$(info CI Metadata: KEYBOARD=$(KEYBOARD)) $(info CI Metadata: KEYBOARD=$(KEYBOARD))
@ -44,7 +43,7 @@ endif
# Object files and generated keymap directory # Object files and generated keymap directory
# To put object files in current directory, use a dot (.), do NOT make # To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro! # this an empty or blank macro!
KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET) INTERMEDIATE_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
ifdef SKIP_VERSION ifdef SKIP_VERSION
OPT_DEFS += -DSKIP_VERSION OPT_DEFS += -DSKIP_VERSION
@ -60,7 +59,7 @@ VERSION_H_FLAGS += --skip-git
endif endif
# Generate the board's version.h file. # 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. # Determine which subfolders exist.
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD) 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) MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
# Pull in rules from info.json # 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) include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c # 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 # Pull in keymap level rules.mk
ifeq ("$(wildcard $(KEYMAP_PATH))", "") ifeq ("$(wildcard $(KEYMAP_PATH))", "")
# Look through the possible keymap folders until we find a matching keymap.c # Look through the possible keymap folders until we find a matching keymap.c
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","") ifneq ($(QMK_USERSPACE),)
-include $(MAIN_KEYMAP_PATH_1)/rules.mk ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c)","")
KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/rules.mk
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","") KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)
-include $(MAIN_KEYMAP_PATH_2)/rules.mk else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c)","")
KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/rules.mk
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2) KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","") KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)
-include $(MAIN_KEYMAP_PATH_3)/rules.mk else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c)","")
KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/rules.mk
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3) KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","") KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)
-include $(MAIN_KEYMAP_PATH_4)/rules.mk else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c)","")
KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/rules.mk
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4) KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","") KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)
-include $(MAIN_KEYMAP_PATH_5)/rules.mk else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c)","")
KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c -include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/rules.mk
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5) KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c
else ifneq ($(LAYOUTS),) KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)
# If we haven't found a keymap yet fall back to community layouts endif
include $(BUILDDEFS_PATH)/build_layout.mk endif
else ifeq ($(KEYMAP_PATH),)
$(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap) ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
# this state should never be reached -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
endif endif
# Have we found a keymap.json? # Have we found a keymap.json?
ifneq ("$(wildcard $(KEYMAP_JSON))", "") ifneq ("$(wildcard $(KEYMAP_JSON))", "")
KEYMAP_C := $(KEYMAP_OUTPUT)/src/keymap.c ifneq ("$(wildcard $(KEYMAP_C))", "")
KEYMAP_H := $(KEYMAP_OUTPUT)/src/config.h $(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 # Load the keymap-level rules.mk if exists
-include $(KEYMAP_PATH)/rules.mk -include $(KEYMAP_PATH)/rules.mk
# Load any rules.mk content from keymap.json # 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) include $(INFO_RULES_MK)
# Add rules to generate the keymap files - indentation here is important # 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) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)) $(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON))
@$(BUILD_CMD) @$(BUILD_CMD)
$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON) $(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON)) $(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON))
@$(BUILD_CMD) @$(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 endif
@ -323,34 +353,34 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json
endif endif
CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
KEYBOARD_SRC += $(KEYBOARD_OUTPUT)/src/default_keyboard.c 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) @$(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) @$(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) @$(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) @$(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) @$(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) @$(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) @$(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) @$(BUILD_CMD)
-include $(KEYMAP_OUTPUT)/src/info_deps.d -include $(INTERMEDIATE_OUTPUT)/src/info_deps.d
.INTERMEDIATE : generated-files .INTERMEDIATE : generated-files
@ -360,6 +390,16 @@ ifeq ("$(USER_NAME)","")
endif endif
USER_PATH := users/$(USER_NAME) 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 # Pull in user level rules.mk
-include $(USER_PATH)/rules.mk -include $(USER_PATH)/rules.mk
ifneq ("$(wildcard $(USER_PATH)/config.h)","") ifneq ("$(wildcard $(USER_PATH)/config.h)","")
@ -400,6 +440,10 @@ ifneq ("$(KEYMAP_H)","")
CONFIG_H += $(KEYMAP_H) CONFIG_H += $(KEYMAP_H)
endif endif
ifeq ($(KEYMAP_C),)
$(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
endif
OPT_DEFS += -DKEYMAP_C=\"$(KEYMAP_C)\" 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 # 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 += $(USER_PATH)
VPATH += $(KEYBOARD_PATHS) VPATH += $(KEYBOARD_PATHS)
VPATH += $(COMMON_VPATH) VPATH += $(COMMON_VPATH)
VPATH += $(KEYBOARD_OUTPUT)/src VPATH += $(INTERMEDIATE_OUTPUT)/src
VPATH += $(KEYMAP_OUTPUT)/src
include $(BUILDDEFS_PATH)/common_features.mk include $(BUILDDEFS_PATH)/common_features.mk
include $(BUILDDEFS_PATH)/generic_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,$(LIB_SRC))
SRC += $(patsubst %.c,%.clib,$(QUANTUM_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)/bootloader.mk
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk
ifneq ($(strip $(PROTOCOL)),) 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 else
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk PROTOCOL_KEY = $(PLATFORM_KEY)
endif endif
include $(TMK_PATH)/protocol/$(PROTOCOL_KEY)/$(PROTOCOL_KEY).mk
# Setup definitions based on the selected MCU # Setup definitions based on the selected MCU
$(eval $(call add_qmk_prefix_defs,MCU_ORIG,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_FAMILY,MCU_FAMILY))
$(eval $(call add_qmk_prefix_defs,MCU_SERIES,MCU_SERIES)) $(eval $(call add_qmk_prefix_defs,MCU_SERIES,MCU_SERIES))
$(eval $(call add_qmk_prefix_defs,BOARD,BOARD)) $(eval $(call add_qmk_prefix_defs,BOARD,BOARD))
$(eval $(call add_qmk_prefix_defs,OPT,OPT))
# Control whether intermediate file listings are generated # Control whether intermediate file listings are generated
# e.g.: # e.g.:
@ -471,17 +513,14 @@ PROJECT_CONFIG := $(CONFIG_H)
CONFIG_H += $(POST_CONFIG_H) CONFIG_H += $(POST_CONFIG_H)
ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H) ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H)
OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT) OUTPUTS := $(INTERMEDIATE_OUTPUT)
$(KEYMAP_OUTPUT)_SRC := $(SRC) $(INTERMEDIATE_OUTPUT)_SRC := $(SRC) $(PLATFORM_SRC)
$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \ $(INTERMEDIATE_OUTPUT)_DEFS := $(OPT_DEFS) \
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(KEYBOARD_OUTPUT)/src/default_keyboard.h\" \ -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\" -DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" \
$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(PROJECT_DEFS)
$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H) $(INTERMEDIATE_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(PROJECT_INC)
$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC) $(INTERMEDIATE_OUTPUT)_CONFIG := $(CONFIG_H) $(PROJECT_CONFIG)
$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS)
$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC)
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
# Default target. # Default target.
all: build check-size all: build check-size
@ -502,10 +541,10 @@ check-size: top-symbols
top-symbols: build top-symbols: build
echo "###########################################" echo "###########################################"
echo "# Highest flash usage:" 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 "###########################################"
echo "# Highest RAM usage:" 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 "###########################################" echo "###########################################"
endif endif

View File

@ -1,6 +1,10 @@
LAYOUTS_PATH := layouts LAYOUTS_PATH := layouts
LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/)))) LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/))))
ifneq ($(QMK_USERSPACE),)
LAYOUTS_REPOS += $(patsubst %/,%,$(QMK_USERSPACE)/$(LAYOUTS_PATH))
endif
define SEARCH_LAYOUTS_REPO define SEARCH_LAYOUTS_REPO
LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP) LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP)
LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json

View File

@ -9,13 +9,13 @@ OPT = g
include paths.mk include paths.mk
include $(BUILDDEFS_PATH)/message.mk include $(BUILDDEFS_PATH)/message.mk
TARGET=test/$(TEST) TARGET=test/$(TEST_OUTPUT)
GTEST_OUTPUT = $(BUILD_DIR)/gtest GTEST_OUTPUT = $(BUILD_DIR)/gtest
TEST_OBJ = $(BUILD_DIR)/test_obj TEST_OBJ = $(BUILD_DIR)/test_obj
OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT) OUTPUTS := $(TEST_OBJ)/$(TEST_OUTPUT) $(GTEST_OUTPUT)
GTEST_INC := \ GTEST_INC := \
$(LIB_PATH)/googletest/googletest/include \ $(LIB_PATH)/googletest/googletest/include \
@ -71,18 +71,18 @@ ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include $(BUILDDEFS_PATH)/build_full_test.mk include $(BUILDDEFS_PATH)/build_full_test.mk
endif endif
$(TEST)_SRC += \ $(TEST_OUTPUT)_SRC += \
tests/test_common/main.cpp \ tests/test_common/main.cpp \
$(QUANTUM_PATH)/logging/print.c $(QUANTUM_PATH)/logging/print.c
ifneq ($(strip $(INTROSPECTION_KEYMAP_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 endif
$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC) $(TEST_OBJ)/$(TEST_OUTPUT)_SRC := $($(TEST_OUTPUT)_SRC)
$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC) $(TEST_OBJ)/$(TEST_OUTPUT)_INC := $($(TEST_OUTPUT)_INC) $(VPATH) $(GTEST_INC)
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS) $(TEST_OBJ)/$(TEST_OUTPUT)_DEFS := $($(TEST_OUTPUT)_DEFS)
$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG) $(TEST_OBJ)/$(TEST_OUTPUT)_CONFIG := $($(TEST_OUTPUT)_CONFIG)
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
include $(BUILDDEFS_PATH)/common_rules.mk include $(BUILDDEFS_PATH)/common_rules.mk

View File

@ -75,10 +75,7 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
endif endif
ifeq ($(strip $(SEQUENCER_ENABLE)), yes) ifeq ($(strip $(SEQUENCER_ENABLE)), yes)
OPT_DEFS += -DSEQUENCER_ENABLE
MUSIC_ENABLE = yes MUSIC_ENABLE = yes
SRC += $(QUANTUM_DIR)/sequencer/sequencer.c
SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c
endif endif
ifeq ($(strip $(MIDI_ENABLE)), yes) ifeq ($(strip $(MIDI_ENABLE)), yes)
@ -94,11 +91,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif endif
MUSIC_ENABLE ?= no
ifeq ($(MUSIC_ENABLE), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
endif
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
STENO_PROTOCOL ?= all STENO_PROTOCOL ?= all
ifeq ($(strip $(STENO_ENABLE)), yes) ifeq ($(strip $(STENO_ENABLE)), yes)
@ -124,17 +116,11 @@ ifeq ($(strip $(STENO_ENABLE)), yes)
endif endif
endif endif
ifeq ($(strip $(VIRTSER_ENABLE)), yes)
OPT_DEFS += -DVIRTSER_ENABLE
endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
OPT_DEFS += -DMOUSEKEY_ENABLE
MOUSE_ENABLE := yes MOUSE_ENABLE := yes
SRC += $(QUANTUM_DIR)/mousekey.c
endif 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 ($(strip $(POINTING_DEVICE_ENABLE)), yes)
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),) 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) $(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 endif
OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER)) OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER))
ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800) ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE SPI_DRIVER_REQUIRED = yes
QUANTUM_LIB_SRC += spi_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick) else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick)
OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE ANALOG_DRIVER_REQUIRED = yes
LIB_SRC += analog.c else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), azoteq_iqs5xx)
I2C_DRIVER_REQUIRED = yes
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c) 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.c
SRC += drivers/sensors/cirque_pinnacle_gestures.c SRC += drivers/sensors/cirque_pinnacle_gestures.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_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) 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.c
SRC += drivers/sensors/cirque_pinnacle_gestures.c SRC += drivers/sensors/cirque_pinnacle_gestures.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_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) else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
QUANTUM_LIB_SRC += i2c_master.c
else ifneq ($(filter $(strip $(POINTING_DEVICE_DRIVER)),pmw3360 pmw3389),) 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 SRC += drivers/sensors/pmw33xx_common.c
QUANTUM_LIB_SRC += spi_master.c
endif endif
endif endif
endif endif
@ -204,12 +186,12 @@ else
else ifeq ($(strip $(EEPROM_DRIVER)), i2c) else ifeq ($(strip $(EEPROM_DRIVER)), i2c)
# External I2C EEPROM implementation # External I2C EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C
QUANTUM_LIB_SRC += i2c_master.c I2C_DRIVER_REQUIRED = yes
SRC += eeprom_driver.c eeprom_i2c.c SRC += eeprom_driver.c eeprom_i2c.c
else ifeq ($(strip $(EEPROM_DRIVER)), spi) else ifeq ($(strip $(EEPROM_DRIVER)), spi)
# External SPI EEPROM implementation # External SPI EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI
QUANTUM_LIB_SRC += spi_master.c SPI_DRIVER_REQUIRED = yes
SRC += eeprom_driver.c eeprom_spi.c SRC += eeprom_driver.c eeprom_spi.c
else ifeq ($(strip $(EEPROM_DRIVER)), legacy_stm32_flash) else ifeq ($(strip $(EEPROM_DRIVER)), legacy_stm32_flash)
# STM32 Emulated EEPROM, backed by MCU flash (soon to be deprecated) # STM32 Emulated EEPROM, backed by MCU flash (soon to be deprecated)
@ -308,23 +290,19 @@ ifneq ($(strip $(FLASH_DRIVER)), none)
else else
OPT_DEFS += -DFLASH_ENABLE OPT_DEFS += -DFLASH_ENABLE
ifeq ($(strip $(FLASH_DRIVER)),spi) ifeq ($(strip $(FLASH_DRIVER)),spi)
SPI_DRIVER_REQUIRED = yes
OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
COMMON_VPATH += $(DRIVER_PATH)/flash COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c SRC += flash_spi.c
QUANTUM_LIB_SRC += spi_master.c
endif endif
endif endif
endif endif
RGBLIGHT_ENABLE ?= no RGBLIGHT_ENABLE ?= no
VALID_RGBLIGHT_TYPES := WS2812 APA102 custom VALID_RGBLIGHT_TYPES := ws2812 apa102 custom
ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
RGBLIGHT_DRIVER ?= custom
endif
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
RGBLIGHT_DRIVER ?= WS2812 RGBLIGHT_DRIVER ?= ws2812
ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),) ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type) $(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
@ -332,197 +310,241 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
COMMON_VPATH += $(QUANTUM_DIR)/rgblight COMMON_VPATH += $(QUANTUM_DIR)/rgblight
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h
OPT_DEFS += -DRGBLIGHT_ENABLE OPT_DEFS += -DRGBLIGHT_ENABLE
OPT_DEFS += -DRGBLIGHT_$(strip $(shell echo $(RGBLIGHT_DRIVER) | tr '[:lower:]' '[:upper:]'))
SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgblight/rgblight.c SRC += $(QUANTUM_DIR)/rgblight/rgblight.c
SRC += $(QUANTUM_DIR)/rgblight/rgblight_drivers.c
CIE1931_CURVE := yes CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes RGB_KEYCODES_ENABLE := yes
endif endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812) ifeq ($(strip $(RGBLIGHT_DRIVER)), ws2812)
WS2812_DRIVER_REQUIRED := yes WS2812_DRIVER_REQUIRED := yes
endif endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102) ifeq ($(strip $(RGBLIGHT_DRIVER)), apa102)
APA102_DRIVER_REQUIRED := yes APA102_DRIVER_REQUIRED := yes
endif endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), custom) ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER OPT_DEFS += -DVELOCIKEY_ENABLE
endif endif
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 LED_MATRIX_ENABLE ?= no
VALID_LED_MATRIX_TYPES := IS31FL3731 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 custom VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3729 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 custom
# TODO: IS31FL3733 IS31FL3737 IS31FL3741
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),) 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) $(call CATASTROPHIC_ERROR,Invalid LED_MATRIX_DRIVER,LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type)
endif endif
OPT_DEFS += -DLED_MATRIX_ENABLE OPT_DEFS += -DLED_MATRIX_ENABLE
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) OPT_DEFS += -DLED_MATRIX_$(strip $(shell echo $(LED_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
OPT_DEFS += -DLIB8_ATTINY
endif
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners 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)/process_keycode/process_backlight.c
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
SRC += $(LIB_PATH)/lib8tion/lib8tion.c LIB8TION_ENABLE := yes
CIE1931_CURVE := yes CIE1931_CURVE := yes
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3218)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731-simple.c SRC += is31fl3218-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3742A) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3729)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3729-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3743A) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3731)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3731-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3745) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3733)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3733-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3746A) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3736)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3736-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), CKLED2001) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3737)
OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3737-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3741)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3741-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3742a-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3743a)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3743a-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3745)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3745-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3746a)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3746a-mono.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), snled27351)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led COMMON_VPATH += $(DRIVER_PATH)/led
SRC += ckled2001-simple.c SRC += snled27351-mono.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
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 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 is31fl3729 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 ws2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),) 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) $(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
endif endif
OPT_DEFS += -DRGB_MATRIX_ENABLE OPT_DEFS += -DRGB_MATRIX_ENABLE
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) OPT_DEFS += -DRGB_MATRIX_$(strip $(shell echo $(RGB_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
OPT_DEFS += -DLIB8_ATTINY
endif
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners 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)/color.c
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
SRC += $(LIB_PATH)/lib8tion/lib8tion.c LIB8TION_ENABLE := yes
CIE1931_CURVE := yes CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes RGB_KEYCODES_ENABLE := yes
ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216) ifeq ($(strip $(RGB_MATRIX_DRIVER)), aw20216s)
OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led COMMON_VPATH += $(DRIVER_PATH)/led
SRC += aw20216.c SRC += aw20216s.c
QUANTUM_LIB_SRC += spi_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3218)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3218.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3729)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3729.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3731)
I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731.c SRC += is31fl3731.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3733)
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3733.c SRC += is31fl3733.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3736) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3736)
OPT_DEFS += -DIS31FL3736 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3736.c SRC += is31fl3736.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3737)
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3737.c SRC += is31fl3737.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3741)
OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3741.c SRC += is31fl3741.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3742A) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3742a)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3742a.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3743A) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3743a)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3743a.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3745) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3745)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3745.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3746A) ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3746a)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c SRC += is31fl3746a.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001) ifeq ($(strip $(RGB_MATRIX_DRIVER)), snled27351)
OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE I2C_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led COMMON_VPATH += $(DRIVER_PATH)/led
SRC += ckled2001.c SRC += snled27351.c
QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812) ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
OPT_DEFS += -DWS2812
WS2812_DRIVER_REQUIRED := yes WS2812_DRIVER_REQUIRED := yes
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102) ifeq ($(strip $(RGB_MATRIX_DRIVER)), apa102)
OPT_DEFS += -DAPA102
APA102_DRIVER_REQUIRED := yes APA102_DRIVER_REQUIRED := yes
endif endif
@ -565,51 +587,23 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
endif endif
COMMON_VPATH += $(QUANTUM_DIR)/backlight COMMON_VPATH += $(QUANTUM_DIR)/backlight
COMMON_VPATH += $(DRIVER_PATH)/backlight
SRC += $(QUANTUM_DIR)/backlight/backlight.c SRC += $(QUANTUM_DIR)/backlight/backlight.c
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
OPT_DEFS += -DBACKLIGHT_ENABLE OPT_DEFS += -DBACKLIGHT_ENABLE
OPT_DEFS += -DBACKLIGHT_$(strip $(shell echo $(BACKLIGHT_DRIVER) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(BACKLIGHT_DRIVER)), custom) ifneq ($(strip $(BACKLIGHT_DRIVER)), custom)
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
else
SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c 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 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 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) ifeq ($(strip $(CIE1931_CURVE)), yes)
OPT_DEFS += -DUSE_CIE1931_CURVE OPT_DEFS += -DUSE_CIE1931_CURVE
LED_TABLES := yes LED_TABLES := yes
@ -624,28 +618,11 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
RAW_ENABLE := yes RAW_ENABLE := yes
BOOTMAGIC_ENABLE := yes BOOTMAGIC_ENABLE := yes
TRI_LAYER_ENABLE := yes TRI_LAYER_ENABLE := yes
SRC += $(QUANTUM_DIR)/via.c
OPT_DEFS += -DVIA_ENABLE
endif endif
VALID_MAGIC_TYPES := yes
BOOTMAGIC_ENABLE ?= no
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid BOOTMAGIC_ENABLE,BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic)
endif
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
OPT_DEFS += -DBOOTMAGIC_LITE
QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_lite.c
endif
endif
COMMON_VPATH += $(QUANTUM_DIR)/bootmagic
QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/magic.c
VALID_CUSTOM_MATRIX_TYPES:= yes lite no VALID_CUSTOM_MATRIX_TYPES:= yes lite no
CUSTOM_MATRIX ?= no CUSTOM_MATRIX ?= no
ifneq ($(strip $(CUSTOM_MATRIX)), yes) ifneq ($(strip $(CUSTOM_MATRIX)), yes)
ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),) ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid CUSTOM_MATRIX,CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type) $(call CATASTROPHIC_ERROR,Invalid CUSTOM_MATRIX,CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type)
@ -710,29 +687,36 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
COMMON_VPATH += $(QUANTUM_PATH)/split_common COMMON_VPATH += $(QUANTUM_PATH)/split_common
endif endif
ifeq ($(strip $(CRC_ENABLE)), yes)
OPT_DEFS += -DCRC_ENABLE
SRC += crc.c
endif
ifeq ($(strip $(FNV_ENABLE)), yes) ifeq ($(strip $(FNV_ENABLE)), yes)
OPT_DEFS += -DFNV_ENABLE OPT_DEFS += -DFNV_ENABLE
VPATH += $(LIB_PATH)/fnv VPATH += $(LIB_PATH)/fnv
SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
endif endif
ifeq ($(strip $(HAPTIC_ENABLE)),yes) ifeq ($(strip $(LIB8TION_ENABLE)), yes)
COMMON_VPATH += $(DRIVER_PATH)/haptic ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), ) OPT_DEFS += -DLIB8_ATTINY
SRC += DRV2605L.c
QUANTUM_LIB_SRC += i2c_master.c
OPT_DEFS += -DDRV2605L
endif endif
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
endif
ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), ) VALID_HAPTIC_DRIVER_TYPES := drv2605l solenoid
SRC += solenoid.c ifeq ($(strip $(HAPTIC_ENABLE)),yes)
OPT_DEFS += -DSOLENOID_ENABLE 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
ifeq ($(strip $(HAPTIC_DRIVER)), drv2605l)
I2C_DRIVER_REQUIRED = yes
SRC += drv2605l.c
endif
ifeq ($(strip $(HAPTIC_DRIVER)), solenoid)
SRC += solenoid.c
endif
endif endif
endif endif
@ -742,8 +726,8 @@ ifeq ($(strip $(HD44780_ENABLE)), yes)
SRC += hd44780.c SRC += hd44780.c
endif endif
VALID_OLED_DRIVER_TYPES := SSD1306 custom VALID_OLED_DRIVER_TYPES := custom ssd1306
OLED_DRIVER ?= SSD1306 OLED_DRIVER ?= ssd1306
VALID_OLED_TRANSPORT_TYPES := i2c spi custom VALID_OLED_TRANSPORT_TYPES := i2c spi custom
OLED_TRANSPORT ?= i2c OLED_TRANSPORT ?= i2c
ifeq ($(strip $(OLED_ENABLE)), yes) ifeq ($(strip $(OLED_ENABLE)), yes)
@ -754,6 +738,7 @@ ifeq ($(strip $(OLED_ENABLE)), yes)
$(call CATASTROPHIC_ERROR,Invalid OLED_TRANSPORT,OLED_TRANSPORT="$(OLED_TRANSPORT)" is not a valid OLED transport) $(call CATASTROPHIC_ERROR,Invalid OLED_TRANSPORT,OLED_TRANSPORT="$(OLED_TRANSPORT)" is not a valid OLED transport)
else else
OPT_DEFS += -DOLED_ENABLE OPT_DEFS += -DOLED_ENABLE
OPT_DEFS += -DOLED_$(strip $(shell echo $(OLED_DRIVER) | tr '[:lower:]' '[:upper:]'))
COMMON_VPATH += $(DRIVER_PATH)/oled COMMON_VPATH += $(DRIVER_PATH)/oled
ifneq ($(strip $(OLED_DRIVER)), custom) ifneq ($(strip $(OLED_DRIVER)), custom)
SRC += oled_driver.c SRC += oled_driver.c
@ -761,10 +746,10 @@ ifeq ($(strip $(OLED_ENABLE)), yes)
OPT_DEFS += -DOLED_TRANSPORT_$(strip $(shell echo $(OLED_TRANSPORT) | tr '[:lower:]' '[:upper:]')) OPT_DEFS += -DOLED_TRANSPORT_$(strip $(shell echo $(OLED_TRANSPORT) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(OLED_TRANSPORT)), i2c) ifeq ($(strip $(OLED_TRANSPORT)), i2c)
QUANTUM_LIB_SRC += i2c_master.c I2C_DRIVER_REQUIRED = yes
endif endif
ifeq ($(strip $(OLED_TRANSPORT)), spi) ifeq ($(strip $(OLED_TRANSPORT)), spi)
QUANTUM_LIB_SRC += spi_master.c SPI_DRIVER_REQUIRED = yes
endif endif
endif endif
endif endif
@ -772,22 +757,24 @@ endif
ifeq ($(strip $(ST7565_ENABLE)), yes) ifeq ($(strip $(ST7565_ENABLE)), yes)
OPT_DEFS += -DST7565_ENABLE OPT_DEFS += -DST7565_ENABLE
SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h
COMMON_VPATH += $(DRIVER_PATH)/lcd COMMON_VPATH += $(DRIVER_PATH)/lcd
QUANTUM_LIB_SRC += spi_master.c
SRC += st7565.c SRC += st7565.c
endif endif
ifeq ($(strip $(UCIS_ENABLE)), yes) ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE OPT_DEFS += -DUCIS_ENABLE
UNICODE_COMMON := yes 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 endif
ifeq ($(strip $(UNICODEMAP_ENABLE)), yes) ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
OPT_DEFS += -DUNICODEMAP_ENABLE OPT_DEFS += -DUNICODEMAP_ENABLE
UNICODE_COMMON := yes 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 endif
ifeq ($(strip $(UNICODE_ENABLE)), yes) ifeq ($(strip $(UNICODE_ENABLE)), yes)
@ -804,27 +791,6 @@ ifeq ($(strip $(UNICODE_COMMON)), yes)
$(QUANTUM_DIR)/unicode/utf8.c $(QUANTUM_DIR)/unicode/utf8.c
endif 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) ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
PS2_ENABLE := yes PS2_ENABLE := yes
MOUSE_ENABLE := yes MOUSE_ENABLE := yes
@ -861,15 +827,12 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
$(call CATASTROPHIC_ERROR,Invalid JOYSTICK_DRIVER,JOYSTICK_DRIVER="$(JOYSTICK_DRIVER)" is not a valid joystick driver) $(call CATASTROPHIC_ERROR,Invalid JOYSTICK_DRIVER,JOYSTICK_DRIVER="$(JOYSTICK_DRIVER)" is not a valid joystick driver)
endif endif
OPT_DEFS += -DJOYSTICK_ENABLE OPT_DEFS += -DJOYSTICK_ENABLE
OPT_DEFS += -DJOYSTICK_$(strip $(shell echo $(JOYSTICK_DRIVER) | tr '[:lower:]' '[:upper:]'))
SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c
SRC += $(QUANTUM_DIR)/joystick.c SRC += $(QUANTUM_DIR)/joystick.c
ifeq ($(strip $(JOYSTICK_DRIVER)), analog) ifeq ($(strip $(JOYSTICK_DRIVER)), analog)
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE ANALOG_DRIVER_REQUIRED = yes
SRC += analog.c
endif
ifeq ($(strip $(JOYSTICK_DRIVER)), digital)
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
endif endif
endif endif
@ -898,29 +861,28 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
endif endif
BLUETOOTH_ENABLE ?= no BLUETOOTH_ENABLE ?= no
VALID_BLUETOOTH_DRIVER_TYPES := BluefruitLE RN42 custom VALID_BLUETOOTH_DRIVER_TYPES := bluefruit_le custom rn42
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),) 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) $(call CATASTROPHIC_ERROR,Invalid BLUETOOTH_DRIVER,BLUETOOTH_DRIVER="$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type)
endif endif
OPT_DEFS += -DBLUETOOTH_ENABLE OPT_DEFS += -DBLUETOOTH_ENABLE
OPT_DEFS += -DBLUETOOTH_$(strip $(shell echo $(BLUETOOTH_DRIVER) | tr '[:lower:]' '[:upper:]'))
NO_USB_STARTUP_CHECK := yes NO_USB_STARTUP_CHECK := yes
COMMON_VPATH += $(DRIVER_PATH)/bluetooth COMMON_VPATH += $(DRIVER_PATH)/bluetooth
SRC += outputselect.c SRC += outputselect.c
ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE) ifeq ($(strip $(BLUETOOTH_DRIVER)), bluefruit_le)
OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE SPI_DRIVER_REQUIRED = yes
ANALOG_DRIVER_REQUIRED = yes
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
QUANTUM_LIB_SRC += analog.c
QUANTUM_LIB_SRC += spi_master.c
endif endif
ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42) ifeq ($(strip $(BLUETOOTH_DRIVER)), rn42)
OPT_DEFS += -DBLUETOOTH_RN42 -DHAL_USE_SERIAL=TRUE UART_DRIVER_REQUIRED = yes
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
SRC += $(DRIVER_PATH)/bluetooth/rn42.c SRC += $(DRIVER_PATH)/bluetooth/rn42.c
QUANTUM_LIB_SRC += uart.c
endif endif
endif endif
@ -932,10 +894,57 @@ ifeq ($(strip $(ENCODER_ENABLE)), yes)
endif endif
endif endif
ifeq ($(strip $(OS_DETECTION_ENABLE)), yes) ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/os_detection.c ifeq ($(strip $(DIP_SWITCH_MAP_ENABLE)), yes)
OPT_DEFS += -DOS_DETECTION_ENABLE OPT_DEFS += -DDIP_SWITCH_MAP_ENABLE
ifeq ($(strip $(OS_DETECTION_DEBUG_ENABLE)), yes)
OPT_DEFS += -DOS_DETECTION_DEBUG_ENABLE
endif 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_$(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

View File

@ -12,6 +12,9 @@ vpath %.hpp $(VPATH_SRC)
vpath %.S $(VPATH_SRC) vpath %.S $(VPATH_SRC)
VPATH := 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 # Convert all SRC to OBJ
define OBJ_FROM_SRC 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)))))) $(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 # For a ChibiOS build, ensure that the board files have the hook overrides injected
define BOARDSRC_INJECT_HOOKS 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 endef
$(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ)))) $(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ))))
@ -188,7 +191,7 @@ DFU_SUFFIX_ARGS ?=
elf: $(BUILD_DIR)/$(TARGET).elf elf: $(BUILD_DIR)/$(TARGET).elf
hex: $(BUILD_DIR)/$(TARGET).hex hex: $(BUILD_DIR)/$(TARGET).hex
uf2: $(BUILD_DIR)/$(TARGET).uf2 uf2: $(BUILD_DIR)/$(TARGET).uf2
cpfirmware: $(FIRMWARE_FORMAT) cpfirmware_qmk: $(FIRMWARE_FORMAT)
$(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD) $(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD)
$(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK) $(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK)
eep: $(BUILD_DIR)/$(TARGET).eep eep: $(BUILD_DIR)/$(TARGET).eep
@ -197,6 +200,15 @@ sym: $(BUILD_DIR)/$(TARGET).sym
LIBNAME=lib$(TARGET).a LIBNAME=lib$(TARGET).a
lib: $(LIBNAME) 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 # 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' 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 # 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) %.elf: $(OBJ) $(MASTER_OUTPUT)/cflags.txt $(MASTER_OUTPUT)/ldflags.txt $(MASTER_OUTPUT)/obj.txt | $(BEGIN)
@$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD) @$(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) @$(BUILD_CMD)
@ -380,31 +392,9 @@ dump_vars:
objs-size: objs-size:
for i in $(OBJ); do echo $$i; done | sort | xargs $(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: 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: check-md5:
$(MD5SUM) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(MD5SUM) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT)

View File

@ -25,7 +25,9 @@ ifneq ($(CONVERT_TO),)
-include $(CONVERTER)/pre_converter.mk -include $(CONVERTER)/pre_converter.mk
PLATFORM_KEY = $(shell echo $(CONVERTER) | cut -d "/" -f2) 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 # Configure any defaults
OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]') OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]')

View File

@ -13,39 +13,53 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
SPACE_CADET_ENABLE ?= yes
GRAVE_ESC_ENABLE ?= yes GRAVE_ESC_ENABLE ?= yes
MAGIC_ENABLE ?= yes
SEND_STRING_ENABLE ?= yes
SPACE_CADET_ENABLE ?= yes
GENERIC_FEATURES = \ GENERIC_FEATURES = \
AUTO_SHIFT \
AUTOCORRECT \ AUTOCORRECT \
BOOTMAGIC \
CAPS_WORD \ CAPS_WORD \
COMBO \ COMBO \
COMMAND \ COMMAND \
CRC \
DEFERRED_EXEC \ DEFERRED_EXEC \
DIGITIZER \ DIGITIZER \
DIP_SWITCH \ DIP_SWITCH \
DYNAMIC_KEYMAP \ DYNAMIC_KEYMAP \
DYNAMIC_MACRO \ DYNAMIC_MACRO \
DYNAMIC_TAPPING_TERM \
GRAVE_ESC \ GRAVE_ESC \
HAPTIC \ HAPTIC \
KEY_LOCK \ KEY_LOCK \
KEY_OVERRIDE \ KEY_OVERRIDE \
LEADER \ LEADER \
MAGIC \
MOUSEKEY \
MUSIC \
OS_DETECTION \
PROGRAMMABLE_BUTTON \ PROGRAMMABLE_BUTTON \
REPEAT_KEY \ REPEAT_KEY \
SECURE \ SECURE \
SEND_STRING \
SEQUENCER \
SPACE_CADET \ SPACE_CADET \
SWAP_HANDS \ SWAP_HANDS \
TAP_DANCE \ TAP_DANCE \
VELOCIKEY \ TRI_LAYER \
VIA \
VIRTSER \
WPM \ WPM \
DYNAMIC_TAPPING_TERM \
TRI_LAYER
define HANDLE_GENERIC_FEATURE define HANDLE_GENERIC_FEATURE
# $$(info "Processing: $1_ENABLE $2.c") # $$(info "Processing: $1_ENABLE $2.c")
SRC += $$(wildcard $$(QUANTUM_DIR)/process_keycode/process_$2.c) SRC += $$(wildcard $$(QUANTUM_DIR)/process_keycode/process_$2.c)
SRC += $$(wildcard $$(QUANTUM_DIR)/$2/$2.c)
SRC += $$(wildcard $$(QUANTUM_DIR)/$2.c) SRC += $$(wildcard $$(QUANTUM_DIR)/$2.c)
VPATH += $$(wildcard $$(QUANTUM_DIR)/$2/)
OPT_DEFS += -D$1_ENABLE OPT_DEFS += -D$1_ENABLE
endef endef

View File

@ -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_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 = 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_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_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 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 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) 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 define CATASTROPHIC_ERROR
$(shell printf "\n * %-99s $(ERROR_STRING)\n" "$2" >&2) $(shell printf "\n * %-99s $(ERROR_STRING)\n" "$2" >&2)
$(error $1) $(error $1)

View File

@ -17,7 +17,7 @@ HARDWARE_OPTION_NAMES = \
BACKLIGHT_ENABLE \ BACKLIGHT_ENABLE \
BACKLIGHT_DRIVER \ BACKLIGHT_DRIVER \
RGBLIGHT_ENABLE \ RGBLIGHT_ENABLE \
RGBLIGHT_CUSTOM_DRIVER \ RGBLIGHT_DRIVER \
RGB_MATRIX_ENABLE \ RGB_MATRIX_ENABLE \
RGB_MATRIX_DRIVER \ RGB_MATRIX_DRIVER \
CIE1931_CURVE \ CIE1931_CURVE \
@ -37,7 +37,6 @@ OTHER_OPTION_NAMES = \
UNICODEMAP_ENABLE \ UNICODEMAP_ENABLE \
UNICODE_COMMON \ UNICODE_COMMON \
AUTO_SHIFT_ENABLE \ AUTO_SHIFT_ENABLE \
AUTO_SHIFT_MODIFIERS \
DYNAMIC_TAPPING_TERM_ENABLE \ DYNAMIC_TAPPING_TERM_ENABLE \
COMBO_ENABLE \ COMBO_ENABLE \
KEY_LOCK_ENABLE \ KEY_LOCK_ENABLE \
@ -60,8 +59,6 @@ OTHER_OPTION_NAMES = \
ENCODER_ENABLE_CUSTOM \ ENCODER_ENABLE_CUSTOM \
GERMAN_ENABLE \ GERMAN_ENABLE \
HAPTIC_ENABLE \ HAPTIC_ENABLE \
HHKB_RN42_ENABLE \
ISSI_ENABLE \
KEYLOGGER_ENABLE \ KEYLOGGER_ENABLE \
LCD_BACKLIGHT_ENABLE \ LCD_BACKLIGHT_ENABLE \
MACROS_ENABLED \ MACROS_ENABLED \

View File

@ -0,0 +1,407 @@
{
"aliases": {
/*
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ # │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ^ │ ¸ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ` │ < │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ « │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ É │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"KC_GRV": {
"key": "FR_HASH",
"label": "#",
}
"KC_1": {
"key": "FR_1",
"label": "1",
}
"KC_2": {
"key": "FR_2",
"label": "2",
}
"KC_3": {
"key": "FR_3",
"label": "3",
}
"KC_4": {
"key": "FR_4",
"label": "4",
}
"KC_5": {
"key": "FR_5",
"label": "5",
}
"KC_6": {
"key": "FR_6",
"label": "6",
}
"KC_7": {
"key": "FR_7",
"label": "7",
}
"KC_8": {
"key": "FR_8",
"label": "8",
}
"KC_9": {
"key": "FR_9",
"label": "9",
}
"KC_0": {
"key": "FR_0",
"label": "0",
}
"KC_MINS": {
"key": "FR_MINS",
"label": "-",
}
"KC_EQL": {
"key": "FR_EQL",
"label": "=",
}
"KC_Q": {
"key": "FR_Q",
"label": "Q",
}
"KC_W": {
"key": "FR_W",
"label": "W",
}
"KC_E": {
"key": "FR_E",
"label": "E",
}
"KC_R": {
"key": "FR_R",
"label": "R",
}
"KC_T": {
"key": "FR_T",
"label": "T",
}
"KC_Y": {
"key": "FR_Y",
"label": "Y",
}
"KC_U": {
"key": "FR_U",
"label": "U",
}
"KC_I": {
"key": "FR_I",
"label": "I",
}
"KC_O": {
"key": "FR_O",
"label": "O",
}
"KC_P": {
"key": "FR_P",
"label": "P",
}
"KC_LBRC": {
"key": "FR_DCIR",
"label": "^ (dead)",
}
"KC_RBRC": {
"key": "FR_CEDL",
"label": "¸ (dead)",
}
"KC_A": {
"key": "FR_A",
"label": "A",
}
"KC_S": {
"key": "FR_S",
"label": "S",
}
"KC_D": {
"key": "FR_D",
"label": "D",
}
"KC_F": {
"key": "FR_F",
"label": "F",
}
"KC_G": {
"key": "FR_G",
"label": "G",
}
"KC_H": {
"key": "FR_H",
"label": "H",
}
"KC_J": {
"key": "FR_J",
"label": "J",
}
"KC_K": {
"key": "FR_K",
"label": "K",
}
"KC_L": {
"key": "FR_L",
"label": "L",
}
"KC_SCLN": {
"key": "FR_SCLN",
"label": ";",
}
"KC_QUOT": {
"key": "FR_DGRV",
"label": "` (dead)",
}
"KC_NUHS": {
"key": "FR_LABK",
"label": "<",
}
"KC_NUBS": {
"key": "FR_LDAQ",
"label": "«",
}
"KC_Z": {
"key": "FR_Z",
"label": "Z",
}
"KC_X": {
"key": "FR_X",
"label": "X",
}
"KC_C": {
"key": "FR_C",
"label": "C",
}
"KC_V": {
"key": "FR_V",
"label": "V",
}
"KC_B": {
"key": "FR_B",
"label": "B",
}
"KC_N": {
"key": "FR_N",
"label": "N",
}
"KC_M": {
"key": "FR_M",
"label": "M",
}
"KC_COMM": {
"key": "FR_COMM",
"label": ",",
}
"KC_DOT": {
"key": "FR_DOT",
"label": ".",
}
"KC_SLSH": {
"key": "FR_EACU",
"label": "É",
}
/* Shifted symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ | │ ! │ " │ / │ $ │ % │ ? │ & │ * │ ( │ ) │ _ │ + │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ │ │ │ │ │ │ │ │ │ │ │ ¨ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ │ │ │ │ │ │ │ : │ │ > │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ » │ │ │ │ │ │ │ │ ' │ │ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"S(FR_HASH)": {
"key": "FR_PIPE",
"label": "|",
}
"S(FR_1)": {
"key": "FR_EXLM",
"label": "!",
}
"S(FR_2)": {
"key": "FR_DQUO",
"label": "\"",
}
"S(FR_3)": {
"key": "FR_SLSH",
"label": "/",
}
"S(FR_4)": {
"key": "FR_DLR",
"label": "$",
}
"S(FR_5)": {
"key": "FR_PERC",
"label": "%",
}
"S(FR_6)": {
"key": "FR_QUES",
"label": "?",
}
"S(FR_7)": {
"key": "FR_AMPR",
"label": "&",
}
"S(FR_8)": {
"key": "FR_ASTR",
"label": "*",
}
"S(FR_9)": {
"key": "FR_LPRN",
"label": "(",
}
"S(FR_0)": {
"key": "FR_RPRN",
"label": ")",
}
"S(FR_MINS)": {
"key": "FR_UNDS",
"label": "_",
}
"S(FR_EQL)": {
"key": "FR_PLUS",
"label": "+",
}
"S(FR_CEDL)": {
"key": "FR_DIAE",
"label": "¨ (dead)",
}
"S(FR_SCLN)": {
"key": "FR_COLN",
"label": ":",
}
"S(FR_LABK)": {
"key": "FR_RABK",
"label": ">",
}
"S(FR_LDAQ)": {
"key": "FR_RDAQ",
"label": "»",
}
"S(FR_COMM)": {
"key": "FR_QUOT",
"label": "'",
}
/* AltGr symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ \ │ ± │ @ │ £ │ ¢ │ ¤ │ ¬ │ ¦ │ ² │ ³ │ ¼ │ ½ │ ¾ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ │ │ │ │ │ │ │ │ § │ ¶ │ [ │ ] │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ │ │ │ │ │ │ │ ~ │ { │ } │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ ° │ │ │ │ │ │ │ µ │ ¯ │ - │ ´ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"ALGR(FR_HASH)": {
"key": "FR_BSLS",
"label": "\\",
}
"ALGR(FR_1)": {
"key": "FR_PLMN",
"label": "±",
}
"ALGR(FR_2)": {
"key": "FR_AT",
"label": "@",
}
"ALGR(FR_3)": {
"key": "FR_PND",
"label": "£",
}
"ALGR(FR_4)": {
"key": "FR_CENT",
"label": "¢",
}
"ALGR(FR_5)": {
"key": "FR_CURR",
"label": "¤",
}
"ALGR(FR_6)": {
"key": "FR_NOT",
"label": "¬",
}
"ALGR(FR_7)": {
"key": "FR_BRKP",
"label": "¦",
}
"ALGR(FR_8)": {
"key": "FR_SUP2",
"label": "²",
}
"ALGR(FR_9)": {
"key": "FR_SUP3",
"label": "³",
}
"ALGR(FR_0)": {
"key": "FR_QRTR",
"label": "¼",
}
"ALGR(FR_MINS)": {
"key": "FR_HALF",
"label": "½",
}
"ALGR(FR_EQL)": {
"key": "FR_TQTR",
"label": "¾",
}
"ALGR(FR_O)": {
"key": "FR_SECT",
"label": "§",
}
"ALGR(FR_P)": {
"key": "FR_PARA",
"label": "¶",
}
"ALGR(FR_DCIR)": {
"key": "FR_LBRC",
"label": "[",
}
"ALGR(FR_CEDL)": {
"key": "FR_RBRC",
"label": "]",
}
"ALGR(FR_SCLN)": {
"key": "FR_TILD",
"label": "~",
}
"ALGR(FR_DGRV)": {
"key": "FR_LCBR",
"label": "{",
}
"ALGR(FR_LABK)": {
"key": "FR_RCBR",
"label": "}",
}
"ALGR(FR_LDAQ)": {
"key": "FR_DEG",
"label": "°",
}
"ALGR(FR_M)": {
"key": "FR_MICR",
"label": "µ",
}
"ALGR(FR_COMM)": {
"key": "FR_MACR",
"label": "¯",
}
"ALGR(FR_DOT)": {
"key": "FR_SHYP",
"label": "­ (soft hyphen)",
}
"ALGR(FR_EACU)": {
"key": "FR_ACUT",
"label": "´ (dead)",
}
}
}

View File

@ -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": "₽",
}
}
}

View File

@ -0,0 +1,339 @@
{
"aliases": {
/*
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ | │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ' │ ¿ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ´ │ + │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ñ │ { │ } │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ < │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ - │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"KC_GRV": {
"key": "ES_PIPE",
"label": "|",
}
"KC_1": {
"key": "ES_1",
"label": "1",
}
"KC_2": {
"key": "ES_2",
"label": "2",
}
"KC_3": {
"key": "ES_3",
"label": "3",
}
"KC_4": {
"key": "ES_4",
"label": "4",
}
"KC_5": {
"key": "ES_5",
"label": "5",
}
"KC_6": {
"key": "ES_6",
"label": "6",
}
"KC_7": {
"key": "ES_7",
"label": "7",
}
"KC_8": {
"key": "ES_8",
"label": "8",
}
"KC_9": {
"key": "ES_9",
"label": "9",
}
"KC_0": {
"key": "ES_0",
"label": "0",
}
"KC_MINS": {
"key": "ES_QUOT",
"label": "'",
}
"KC_EQL": {
"key": "ES_IQUE",
"label": "¿",
}
"KC_Q": {
"key": "ES_Q",
"label": "Q",
}
"KC_W": {
"key": "ES_W",
"label": "W",
}
"KC_E": {
"key": "ES_E",
"label": "E",
}
"KC_R": {
"key": "ES_R",
"label": "R",
}
"KC_T": {
"key": "ES_T",
"label": "T",
}
"KC_Y": {
"key": "ES_Y",
"label": "Y",
}
"KC_U": {
"key": "ES_U",
"label": "U",
}
"KC_I": {
"key": "ES_I",
"label": "I",
}
"KC_O": {
"key": "ES_O",
"label": "O",
}
"KC_P": {
"key": "ES_P",
"label": "P",
}
"KC_LBRC": {
"key": "ES_ACUT",
"label": "´ (dead)",
}
"KC_RBRC": {
"key": "ES_PLUS",
"label": "+",
}
"KC_A": {
"key": "ES_A",
"label": "A",
}
"KC_S": {
"key": "ES_S",
"label": "S",
}
"KC_D": {
"key": "ES_D",
"label": "D",
}
"KC_F": {
"key": "ES_F",
"label": "F",
}
"KC_G": {
"key": "ES_G",
"label": "G",
}
"KC_H": {
"key": "ES_H",
"label": "H",
}
"KC_J": {
"key": "ES_J",
"label": "J",
}
"KC_K": {
"key": "ES_K",
"label": "K",
}
"KC_L": {
"key": "ES_L",
"label": "L",
}
"KC_SCLN": {
"key": "ES_NTIL",
"label": "Ñ",
}
"KC_QUOT": {
"key": "ES_LCBR",
"label": "{",
}
"KC_NUHS": {
"key": "ES_RCBR",
"label": "}",
}
"KC_NUBS": {
"key": "ES_LABK",
"label": "<",
}
"KC_Z": {
"key": "ES_Z",
"label": "Z",
}
"KC_X": {
"key": "ES_X",
"label": "X",
}
"KC_C": {
"key": "ES_C",
"label": "C",
}
"KC_V": {
"key": "ES_V",
"label": "V",
}
"KC_B": {
"key": "ES_B",
"label": "B",
}
"KC_N": {
"key": "ES_N",
"label": "N",
}
"KC_M": {
"key": "ES_M",
"label": "M",
}
"KC_COMM": {
"key": "ES_COMM",
"label": ",",
}
"KC_DOT": {
"key": "ES_DOT",
"label": ".",
}
"KC_SLSH": {
"key": "ES_MINS",
"label": "-",
}
/* Shifted symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ ° │ ! │ " │ # │ $ │ % │ & │ / │ ( │ ) │ = │ ? │ ¡ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ │ │ │ │ │ │ │ │ │ │ ¨ │ * │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ │ │ │ │ │ │ │ │ [ │ ] │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ > │ │ │ │ │ │ │ │ ; │ : │ _ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"S(ES_PIPE)": {
"key": "ES_MORD",
"label": "°",
}
"S(ES_1)": {
"key": "ES_EXLM",
"label": "!",
}
"S(ES_2)": {
"key": "ES_DQUO",
"label": "\"",
}
"S(ES_3)": {
"key": "ES_NUMB",
"label": "#",
}
"S(ES_4)": {
"key": "ES_DLR",
"label": "$",
}
"S(ES_5)": {
"key": "ES_PERC",
"label": "%",
}
"S(ES_6)": {
"key": "ES_AMPR",
"label": "&",
}
"S(ES_7)": {
"key": "ES_SLSH",
"label": "/",
}
"S(ES_8)": {
"key": "ES_LPRN",
"label": "(",
}
"S(ES_9)": {
"key": "ES_RPRN",
"label": ")",
}
"S(ES_0)": {
"key": "ES_EQL",
"label": "=",
}
"S(ES_QUOT)": {
"key": "ES_QUES",
"label": "?",
}
"S(ES_IQUE)": {
"key": "ES_IEXL",
"label": "¡",
}
"S(ES_ACUT)": {
"key": "ES_DIAE",
"label": "¨ (dead)",
}
"S(ES_PLUS)": {
"key": "ES_ASTR",
"label": "*",
}
"S(ES_LCBR)": {
"key": "ES_LBRC",
"label": "[",
}
"S(ES_RCBR)": {
"key": "ES_RBRC",
"label": "]",
}
"S(ES_LABK)": {
"key": "ES_RABK",
"label": ">",
}
"S(ES_COMM)": {
"key": "ES_SCLN",
"label": ";",
}
"S(ES_DOT)": {
"key": "ES_COLN",
"label": ":",
}
"S(ES_MINS)": {
"key": "ES_UNDS",
"label": "_",
}
/* AltGr symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ ¬ │ │ │ │ │ │ │ │ │ │ │ \ │ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ @ │ │ │ │ │ │ │ │ │ │ │ ~ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ │ │ │ │ │ │ │ │ ^ │ ` │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ │ │ │ │ │ │ │ │ │ │ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"ALGR(ES_PIPE)": {
"key": "ES_NOT",
"label": "¬",
}
"ALGR(ES_QUOT)": {
"key": "ES_BSLS",
"label": "\\",
}
"ALGR(ES_Q)": {
"key": "ES_AT",
"label": "@",
}
"ALGR(ES_PLUS)": {
"key": "ES_TILD",
"label": "~",
}
"ALGR(ES_LCBR)": {
"key": "ES_CIRC",
"label": "^",
}
}
}

View File

@ -1,84 +1,89 @@
{ {
"development_board": { "development_board": {
"promicro": {
"processor": "atmega32u4",
"bootloader": "caterina",
"pin_compatible": "promicro"
},
"elite_c": {
"processor": "atmega32u4",
"bootloader": "atmel-dfu",
"pin_compatible": "promicro"
},
"elite_pi": {
"processor": "RP2040",
"bootloader": "rp2040",
"board": "QMK_PM2040"
},
"proton_c": {
"processor": "STM32F303",
"bootloader": "stm32-dfu",
"board": "QMK_PROTON_C"
},
"kb2040": {
"processor": "RP2040",
"bootloader": "rp2040",
"board": "QMK_PM2040"
},
"promicro_rp2040": {
"processor": "RP2040",
"bootloader": "rp2040",
"board": "QMK_PM2040"
},
"blok": {
"processor": "RP2040",
"bootloader": "rp2040",
"board": "QMK_BLOK"
},
"michi": {
"processor": "RP2040",
"bootloader": "rp2040",
"board": "QMK_PM2040"
},
"bit_c_pro": { "bit_c_pro": {
"processor": "RP2040", "board": "QMK_PM2040",
"bootloader": "rp2040", "bootloader": "rp2040",
"board": "QMK_PM2040" "processor": "RP2040"
},
"bluepill": {
"processor": "STM32F103",
"bootloader": "stm32duino",
"board": "STM32_F103_STM32DUINO"
}, },
"blackpill_f401": { "blackpill_f401": {
"processor": "STM32F401", "board": "BLACKPILL_STM32_F401",
"bootloader": "stm32-dfu", "bootloader": "stm32-dfu",
"board": "BLACKPILL_STM32_F401" "processor": "STM32F401"
}, },
"blackpill_f411": { "blackpill_f411": {
"processor": "STM32F411", "board": "BLACKPILL_STM32_F411",
"bootloader": "stm32-dfu", "bootloader": "stm32-dfu",
"board": "BLACKPILL_STM32_F411" "processor": "STM32F411"
}, },
"stemcell": { "blok": {
"processor": "STM32F411", "board": "QMK_BLOK",
"bootloader": "tinyuf2", "bootloader": "rp2040",
"board": "STEMCELL" "processor": "RP2040"
},
"bluepill": {
"board": "STM32_F103_STM32DUINO",
"bootloader": "stm32duino",
"processor": "STM32F103"
}, },
"bonsai_c4": { "bonsai_c4": {
"processor": "STM32F411", "board": "BONSAI_C4",
"bootloader": "stm32-dfu", "bootloader": "stm32-dfu",
"board": "BONSAI_C4" "processor": "STM32F411"
},
"elite_c": {
"bootloader": "atmel-dfu",
"pin_compatible": "promicro",
"processor": "atmega32u4"
},
"elite_pi": {
"board": "QMK_PM2040",
"bootloader": "rp2040",
"processor": "RP2040"
}, },
"helios": { "helios": {
"board": "QMK_PM2040",
"bootloader": "rp2040",
"processor": "RP2040"
},
"imera": {
"processor": "RP2040", "processor": "RP2040",
"bootloader": "rp2040", "bootloader": "rp2040",
"board": "QMK_PM2040" "board": "QMK_PM2040"
}, },
"liatris": { "kb2040": {
"processor": "RP2040", "board": "QMK_PM2040",
"bootloader": "rp2040", "bootloader": "rp2040",
"board": "QMK_PM2040" "processor": "RP2040"
},
"liatris": {
"board": "QMK_PM2040",
"bootloader": "rp2040",
"processor": "RP2040"
},
"michi": {
"board": "QMK_PM2040",
"bootloader": "rp2040",
"processor": "RP2040"
},
"promicro": {
"bootloader": "caterina",
"pin_compatible": "promicro",
"processor": "atmega32u4"
},
"promicro_rp2040": {
"board": "QMK_PM2040",
"bootloader": "rp2040",
"processor": "RP2040"
},
"proton_c": {
"board": "QMK_PROTON_C",
"bootloader": "stm32-dfu",
"processor": "STM32F303"
},
"stemcell": {
"board": "STEMCELL",
"bootloader": "tinyuf2",
"processor": "STM32F411"
} }
} }
} }

View File

@ -3,7 +3,7 @@
{ {
// Format: // Format:
// <config.h key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]} // <config.h key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]}
// value_type: one of "array", "array.int", "bool", "int", "hex", "list", "mapping", "str", "raw" // value_type: one of "array", "array.int", "bool, "flag", "int", "hex", "list", "mapping", "str", "raw"
// to_json: Default `true`. Set to `false` to exclude this mapping from info.json // to_json: Default `true`. Set to `false` to exclude this mapping from info.json
// to_c: Default `true`. Set to `false` to exclude this mapping from config.h // to_c: Default `true`. Set to `false` to exclude this mapping from config.h
// warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places // warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places
@ -17,18 +17,23 @@
"APA102_DI_PIN": {"info_key": "apa102.data_pin"}, "APA102_DI_PIN": {"info_key": "apa102.data_pin"},
// Audio // Audio
"AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "bool"}, "AUDIO_DEFAULT_ON": {"info_key": "audio.default.on", "value_type": "bool"},
"SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "bool"}, "AUDIO_DEFAULT_CLICKY_ON": {"info_key": "audio.default.clicky", "value_type": "bool"},
"AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "flag"},
"SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "flag"},
// Backlight // Backlight
"BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "bool"}, "BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "flag"},
"BACKLIGHT_CAPS_LOCK": {"info_key": "backlight.as_caps_lock", "value_type": "bool"}, "BACKLIGHT_CAPS_LOCK": {"info_key": "backlight.as_caps_lock", "value_type": "flag"},
"BACKLIGHT_LEVELS": {"info_key": "backlight.levels", "value_type": "int"}, "BACKLIGHT_LEVELS": {"info_key": "backlight.levels", "value_type": "int"},
"BACKLIGHT_LIMIT_VAL": {"info_key": "backlight.max_brightness", "value_type": "int"}, "BACKLIGHT_LIMIT_VAL": {"info_key": "backlight.max_brightness", "value_type": "int"},
"BACKLIGHT_ON_STATE": {"info_key": "backlight.on_state", "value_type": "int"}, "BACKLIGHT_ON_STATE": {"info_key": "backlight.on_state", "value_type": "int"},
"BACKLIGHT_PIN": {"info_key": "backlight.pin"}, "BACKLIGHT_PIN": {"info_key": "backlight.pin"},
"BACKLIGHT_PINS": {"info_key": "backlight.pins", "value_type": "array"}, "BACKLIGHT_PINS": {"info_key": "backlight.pins", "value_type": "array"},
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"}, "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
"BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"}, "BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"},
@ -37,18 +42,26 @@
"BOOTMAGIC_LITE_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"}, "BOOTMAGIC_LITE_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"},
// Caps Word // Caps Word
"BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "bool"}, "BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "flag"},
"CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"}, "CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"},
"CAPS_WORD_INVERT_ON_SHIFT": {"info_key": "caps_word.invert_on_shift", "value_type": "bool"}, "CAPS_WORD_INVERT_ON_SHIFT": {"info_key": "caps_word.invert_on_shift", "value_type": "flag"},
"DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.double_tap_shift_turns_on", "value_type": "bool"}, "DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.double_tap_shift_turns_on", "value_type": "flag"},
// Combos // Combos
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"}, "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
"DYNAMIC_KEYMAP_EEPROM_MAX_ADDR": {"info_key": "dynamic_keymap.eeprom_max_addr", "value_type": "int"}, "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"}, "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 // Indicators
"LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"}, "LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"},
"LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"}, "LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"},
@ -58,19 +71,29 @@
"LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"}, "LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"},
// Leader Key // Leader Key
"LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "bool"}, "LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "flag"},
"LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "bool"}, "LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "flag"},
"LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"}, "LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"},
// LED Matrix // LED Matrix
"LED_MATRIX_CENTER": {"info_key": "led_matrix.center_point", "value_type": "array.int"}, "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": "flag"},
"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_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_SLEEP": {"info_key": "led_matrix.sleep", "value_type": "flag"},
"LED_MATRIX_SPD_STEP": {"info_key": "led_matrix.speed_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_SPLIT": {"info_key": "led_matrix.split_count", "value_type": "array.int"},
"LED_MATRIX_TIMEOUT": {"info_key": "led_matrix.timeout", "value_type": "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_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": "flag"},
"LOCKING_RESYNC_ENABLE": {"info_key": "qmk.locking.resync", "value_type": "flag"},
// LUFA Bootloader // LUFA Bootloader
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"}, "QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
@ -81,7 +104,7 @@
// Matrix // Matrix
"DEBOUNCE": {"info_key": "debounce", "value_type": "int"}, "DEBOUNCE": {"info_key": "debounce", "value_type": "int"},
"DIODE_DIRECTION": {"info_key": "diode_direction"}, "DIODE_DIRECTION": {"info_key": "diode_direction"},
"MATRIX_HAS_GHOST": {"info_key": "matrix_pins.ghost", "value_type": "bool"}, "MATRIX_HAS_GHOST": {"info_key": "matrix_pins.ghost", "value_type": "flag"},
"MATRIX_INPUT_PRESSED_STATE": {"info_key": "matrix_pins.input_pressed_state", "value_type": "int"}, "MATRIX_INPUT_PRESSED_STATE": {"info_key": "matrix_pins.input_pressed_state", "value_type": "int"},
"MATRIX_IO_DELAY": {"info_key": "matrix_pins.io_delay", "value_type": "int"}, "MATRIX_IO_DELAY": {"info_key": "matrix_pins.io_delay", "value_type": "int"},
@ -103,27 +126,43 @@
// RGB Matrix // RGB Matrix
"RGB_MATRIX_CENTER": {"info_key": "rgb_matrix.center_point", "value_type": "array.int"}, "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_HUE_STEP": {"info_key": "rgb_matrix.hue_steps", "value_type": "int"},
"RGB_MATRIX_KEYRELEASES": {"info_key": "rgb_matrix.react_on_keyup", "value_type": "flag"},
"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_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_SAT_STEP": {"info_key": "rgb_matrix.sat_steps", "value_type": "int"},
"RGB_MATRIX_SLEEP": {"info_key": "rgb_matrix.sleep", "value_type": "flag"},
"RGB_MATRIX_SPD_STEP": {"info_key": "rgb_matrix.speed_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_SPLIT": {"info_key": "rgb_matrix.split_count", "value_type": "array.int"},
"RGB_MATRIX_TIMEOUT": {"info_key": "rgb_matrix.timeout", "value_type": "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_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 // RGBLight
"RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"},
"RGBLED_SPLIT": {"info_key": "rgblight.split_count", "value_type": "array.int"}, "RGBLED_SPLIT": {"info_key": "rgblight.split_count", "value_type": "array.int"},
"RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"}, "RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"},
"RGBLIGHT_LAYER_BLINK": {"info_key": "rgblight.layers.blink", "value_type": "bool"}, "RGBLIGHT_LAYER_BLINK": {"info_key": "rgblight.layers.blink", "value_type": "flag"},
"RGBLIGHT_LAYERS": {"info_key": "rgblight.layers.enabled", "value_type": "bool"}, "RGBLIGHT_LAYERS": {"info_key": "rgblight.layers.enabled", "value_type": "flag"},
"RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF": {"info_key": "rgblight.layers.override_rgb", "value_type": "bool"}, "RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF": {"info_key": "rgblight.layers.override_rgb", "value_type": "flag"},
"RGBLIGHT_LED_COUNT": {"info_key": "rgblight.led_count", "value_type": "int"},
"RGBLIGHT_LED_MAP": {"info_key": "rgblight.led_map", "value_type": "array.int"},
"RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"}, "RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"},
"RGBLIGHT_MAX_LAYERS": {"info_key": "rgblight.layers.max", "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_SAT_STEP": {"info_key": "rgblight.saturation_steps", "value_type": "int"},
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"}, "RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "flag"},
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"}, "RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "flag"},
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"}, "RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"}, "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": "flag"},
// Secure // Secure
"SECURE_IDLE_TIMEOUT": {"info_key": "secure.idle_timeout", "value_type": "int"}, "SECURE_IDLE_TIMEOUT": {"info_key": "secure.idle_timeout", "value_type": "int"},
@ -133,29 +172,39 @@
// Split Keyboard // Split Keyboard
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"}, "SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"}, "SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
"SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"}, "SPLIT_HAND_MATRIX_GRID": {"info_key": "split.handedness.matrix_grid", "value_type": "array", "to_c": false},
"SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"}, "SPLIT_HAND_PIN": {"info_key": "split.handedness.pin"},
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"}, "SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "flag"},
"SPLIT_USB_TIMEOUT": {"info_key": "split.usb_detect.timeout", "value_type": "int"}, "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_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_ENABLE": {"info_key": "split.transport.watchdog", "value_type": "flag"},
"SPLIT_WATCHDOG_TIMEOUT": {"info_key": "split.transport.watchdog_timeout", "value_type": "int"}, "SPLIT_WATCHDOG_TIMEOUT": {"info_key": "split.transport.watchdog_timeout", "value_type": "int"},
"SPLIT_ACTIVITY_ENABLE": {"info_key": "split.transport.sync.activity", "value_type": "flag"},
"SPLIT_DETECTED_OS_ENABLE": {"info_key": "split.transport.sync.detected_os", "value_type": "flag"},
"SPLIT_HAPTIC_ENABLE": {"info_key": "split.transport.sync.haptic", "value_type": "flag"},
"SPLIT_LAYER_STATE_ENABLE": {"info_key": "split.transport.sync.layer_state", "value_type": "flag"},
"SPLIT_LED_STATE_ENABLE": {"info_key": "split.transport.sync.indicators", "value_type": "flag"},
"SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync.matrix_state", "value_type": "flag"},
"SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync.modifiers", "value_type": "flag"},
"SPLIT_OLED_ENABLE": {"info_key": "split.transport.sync.oled", "value_type": "flag"},
"SPLIT_ST7565_ENABLE": {"info_key": "split.transport.sync.st7565", "value_type": "flag"},
"SPLIT_WPM_ENABLE": {"info_key": "split.transport.sync.wpm", "value_type": "flag"},
// Tapping // Tapping
"HOLD_ON_OTHER_KEY_PRESS": {"info_key": "tapping.hold_on_other_key_press", "value_type": "bool"}, "HOLD_ON_OTHER_KEY_PRESS": {"info_key": "tapping.hold_on_other_key_press", "value_type": "flag"},
"HOLD_ON_OTHER_KEY_PRESS_PER_KEY": {"info_key": "tapping.hold_on_other_key_press_per_key", "value_type": "bool"}, "HOLD_ON_OTHER_KEY_PRESS_PER_KEY": {"info_key": "tapping.hold_on_other_key_press_per_key", "value_type": "flag"},
"PERMISSIVE_HOLD": {"info_key": "tapping.permissive_hold", "value_type": "bool"}, "PERMISSIVE_HOLD": {"info_key": "tapping.permissive_hold", "value_type": "flag"},
"PERMISSIVE_HOLD_PER_KEY": {"info_key": "tapping.permissive_hold_per_key", "value_type": "bool"}, "PERMISSIVE_HOLD_PER_KEY": {"info_key": "tapping.permissive_hold_per_key", "value_type": "flag"},
"RETRO_TAPPING": {"info_key": "tapping.retro", "value_type": "bool"}, "RETRO_TAPPING": {"info_key": "tapping.retro", "value_type": "flag"},
"RETRO_TAPPING_PER_KEY": {"info_key": "tapping.retro_per_key", "value_type": "bool"}, "RETRO_TAPPING_PER_KEY": {"info_key": "tapping.retro_per_key", "value_type": "flag"},
"TAP_CODE_DELAY": {"info_key": "qmk.tap_keycode_delay", "value_type": "int"}, "TAP_CODE_DELAY": {"info_key": "qmk.tap_keycode_delay", "value_type": "int"},
"TAP_HOLD_CAPS_DELAY": {"info_key": "qmk.tap_capslock_delay", "value_type": "int"}, "TAP_HOLD_CAPS_DELAY": {"info_key": "qmk.tap_capslock_delay", "value_type": "int"},
"TAPPING_TERM": {"info_key": "tapping.term", "value_type": "int"}, "TAPPING_TERM": {"info_key": "tapping.term", "value_type": "int"},
"TAPPING_TERM_PER_KEY": {"info_key": "tapping.term_per_key", "value_type": "bool"}, "TAPPING_TERM_PER_KEY": {"info_key": "tapping.term_per_key", "value_type": "flag"},
"TAPPING_TOGGLE": {"info_key": "tapping.toggle", "value_type": "int"}, "TAPPING_TOGGLE": {"info_key": "tapping.toggle", "value_type": "int"},
// USB // USB
"FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "bool"}, "FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "flag"},
"USB_MAX_POWER_CONSUMPTION": {"info_key": "usb.max_power", "value_type": "int"}, "USB_MAX_POWER_CONSUMPTION": {"info_key": "usb.max_power", "value_type": "int"},
"USB_POLLING_INTERVAL_MS": {"info_key": "usb.polling_interval", "value_type": "int"}, "USB_POLLING_INTERVAL_MS": {"info_key": "usb.polling_interval", "value_type": "int"},
"USB_SUSPEND_WAKEUP_DELAY": {"info_key": "usb.suspend_wakeup_delay", "value_type": "int"}, "USB_SUSPEND_WAKEUP_DELAY": {"info_key": "usb.suspend_wakeup_delay", "value_type": "int"},
@ -170,16 +219,18 @@
// Items we want flagged in lint // Items we want flagged in lint
"DEBOUNCING_DELAY": {"info_key": "_invalid.debouncing_delay", "invalid": true, "replace_with": "DEBOUNCE"}, "DEBOUNCING_DELAY": {"info_key": "_invalid.debouncing_delay", "invalid": true, "replace_with": "DEBOUNCE"},
"DESCRIPTION": {"info_key": "_invalid.usb_description", "invalid": true}, "DESCRIPTION": {"info_key": "_invalid.usb_description", "invalid": true},
"IGNORE_MOD_TAP_INTERRUPT": {"info_key": "_invalid.ignore_mod_tap_interrupt", "value_type": "bool", "invalid": true}, "IGNORE_MOD_TAP_INTERRUPT": {"info_key": "_invalid.ignore_mod_tap_interrupt", "value_type": "flag", "invalid": true},
"IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true} "IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true},
"LED_DISABLE_WHEN_USB_SUSPENDED": {"info_key": "_invalid.led_matrix_sleep", "invalid": true, "replace_with": "LED_MATRIX_SLEEP"},
"NO_ACTION_FUNCTION": {"info_key": "_invalid.no_action_function", "invalid": true}, "NO_ACTION_FUNCTION": {"info_key": "_invalid.no_action_function", "invalid": true},
"NO_ACTION_MACRO": {"info_key": "_invalid.no_action_macro", "invalid": true}, "NO_ACTION_MACRO": {"info_key": "_invalid.no_action_macro", "invalid": true},
"PREVENT_STUCK_MODIFIERS": {"info_key": "_invalid.prevent_stuck_mods", "invalid": true}, "PREVENT_STUCK_MODIFIERS": {"info_key": "_invalid.prevent_stuck_mods", "invalid": true},
"QMK_KEYS_PER_SCAN": {"info_key": "qmk.keys_per_scan", "value_type": "int", "deprecated": true}, "QMK_KEYS_PER_SCAN": {"info_key": "qmk.keys_per_scan", "value_type": "int", "deprecated": true},
"RGB_DI_PIN": {"info_key": "rgblight.pin", "invalid": true, "replace_with": "WS2812_DI_PIN or APA102_DI_PIN"}, "RGB_DI_PIN": {"info_key": "rgblight.pin", "invalid": true, "replace_with": "WS2812_DI_PIN or APA102_DI_PIN"},
"RGBLIGHT_ANIMATIONS": {"info_key": "_invalid.rgblight.animations.all", "value_type": "bool", "invalid": true}, "RGB_DISABLE_WHEN_USB_SUSPENDED": {"info_key": "_invalid.rgb_matrix_sleep", "invalid": true, "replace_with": "RGB_MATRIX_SLEEP"},
"TAPPING_FORCE_HOLD": {"info_key": "tapping.force_hold", "value_type": "bool", "deprecated": true}, "RGBLIGHT_ANIMATIONS": {"info_key": "_invalid.rgblight.animations.all", "value_type": "flag", "invalid": true},
"TAPPING_FORCE_HOLD_PER_KEY": {"info_key": "tapping.force_hold_per_key", "value_type": "bool", "deprecated": true}, "TAPPING_FORCE_HOLD": {"info_key": "tapping.force_hold", "value_type": "flag", "deprecated": true},
"TAPPING_FORCE_HOLD_PER_KEY": {"info_key": "tapping.force_hold_per_key", "value_type": "flag", "deprecated": true},
"UNUSED_PINS": {"info_key": "_invalid.unused_pins", "deprecated": true}, "UNUSED_PINS": {"info_key": "_invalid.unused_pins", "deprecated": true},
"COMBO_COUNT": {"info_key": "_invalid.combo.count", "invalid": true}, "COMBO_COUNT": {"info_key": "_invalid.combo.count", "invalid": true},
@ -189,4 +240,9 @@
"PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false, "value_type": "str", "deprecated": true, "replace_with": "`keyboard_name` in info.json"}, "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"}, "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"}, "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}
} }

View File

@ -17,6 +17,7 @@
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false}, "BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
"BOOTMAGIC_ENABLE": {"info_key": "bootmagic.enabled", "value_type": "bool"}, "BOOTMAGIC_ENABLE": {"info_key": "bootmagic.enabled", "value_type": "bool"},
"CAPS_WORD_ENABLE": {"info_key": "caps_word.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"}, "DEBOUNCE_TYPE": {"info_key": "build.debounce_type"},
"EEPROM_DRIVER": {"info_key": "eeprom.driver"}, "EEPROM_DRIVER": {"info_key": "eeprom.driver"},
"ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"}, "ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
@ -35,12 +36,14 @@
"PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"}, "PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
"PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"}, "PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
"RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"}, "RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"},
"RGBLIGHT_DRIVER": {"info_key": "rgblight.driver"},
"SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"}, "SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"},
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"}, "SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false}, "SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false},
"STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"}, "STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"},
"STENO_PROTOCOL": {"info_key": "stenography.protocol"}, "STENO_PROTOCOL": {"info_key": "stenography.protocol"},
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"}, "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"}, "WS2812_DRIVER": {"info_key": "ws2812.driver"},
// Items we want flagged in lint // Items we want flagged in lint

View File

@ -1,13 +1,16 @@
{ {
// Format for each entry: // Format for each entry:
// "<alias>": { // "<alias>": {
// "target": "<keyboard_folder>", // "target": "<keyboard_folder>"
// "layouts": {
// "<layout_alias>": "<layout_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": { "2_milk": {
"target": "spaceman/2_milk" "target": "spaceman/2_milk"
}, },
@ -39,7 +42,7 @@
"target": "amjkeyboard/amjpad" "target": "amjkeyboard/amjpad"
}, },
"angel64": { "angel64": {
"target": "angel64/alpha" "target": "kakunpc/angel64/alpha"
}, },
"ashpil/modelm_usbc": { "ashpil/modelm_usbc": {
"target": "ibm/model_m/ashpil_usbc" "target": "ibm/model_m/ashpil_usbc"
@ -51,10 +54,10 @@
"target": "viktus/at101_bh" "target": "viktus/at101_bh"
}, },
"atom47/rev2": { "atom47/rev2": {
"target": "maartenwut/atom47/rev2" "target": "evyd13/atom47/rev2"
}, },
"atom47/rev3": { "atom47/rev3": {
"target": "maartenwut/atom47/rev3" "target": "evyd13/atom47/rev3"
}, },
"bakeneko60": { "bakeneko60": {
"target": "kkatano/bakeneko60" "target": "kkatano/bakeneko60"
@ -69,7 +72,7 @@
"target": "bear_face/v1" "target": "bear_face/v1"
}, },
"bm16a": { "bm16a": {
"target": "kprepublic/bm16a" "target": "kprepublic/bm16a/v1"
}, },
"bm16s": { "bm16s": {
"target": "kprepublic/bm16s" "target": "kprepublic/bm16s"
@ -81,16 +84,16 @@
"target": "kprepublic/bm43a" "target": "kprepublic/bm43a"
}, },
"bm60poker": { "bm60poker": {
"target": "kprepublic/bm60poker" "target": "kprepublic/bm60hsrgb_poker/rev1"
}, },
"bm60rgb": { "bm60rgb": {
"target": "kprepublic/bm60rgb" "target": "kprepublic/bm60hsrgb/rev1"
}, },
"bm60rgb_iso": { "bm60rgb_iso": {
"target": "kprepublic/bm60rgb_iso" "target": "kprepublic/bm60hsrgb_iso/rev1"
}, },
"bm68rgb": { "bm68rgb": {
"target": "kprepublic/bm68rgb" "target": "kprepublic/bm68hsrgb/rev1"
}, },
"bpiphany/pegasushoof": { "bpiphany/pegasushoof": {
"target": "bpiphany/pegasushoof/2013" "target": "bpiphany/pegasushoof/2013"
@ -140,26 +143,17 @@
"daisy": { "daisy": {
"target": "ktec/daisy" "target": "ktec/daisy"
}, },
"doro67/multi": { "dp3000": {
"layouts": { "target": "dp3000/rev1"
"LAYOUT_ansi": "LAYOUT_65_ansi_blocker"
}
},
"doro67/regular": {
"layouts": {
"LAYOUT": "LAYOUT_65_ansi_blocker"
}
},
"doro67/rgb": {
"layouts": {
"LAYOUT": "LAYOUT_65_ansi_blocker"
}
}, },
"drakon": { "drakon": {
"target": "jagdpietr/drakon" "target": "jagdpietr/drakon"
}, },
"durgod/k320": { "durgod/k320": {
"target": "durgod/k3x0/k320" "target": "durgod/k320/base"
},
"durgod/k3x0/k320": {
"target": "durgod/k320/base"
}, },
"durgod/hades": { "durgod/hades": {
"target": "durgod/dgk6x/hades_ansi" "target": "durgod/dgk6x/hades_ansi"
@ -185,9 +179,15 @@
"dztech/volcano660": { "dztech/volcano660": {
"target": "ilumkb/volcano660" "target": "ilumkb/volcano660"
}, },
"dztech/og60": {
"target": "dztech/tofu60"
},
"eek": { "eek": {
"target": "eek/silk_down" "target": "eek/silk_down"
}, },
"era/klein": {
"target": "era/sirind/klein_sd"
},
"ergodone": { "ergodone": {
"target": "ktec/ergodone" "target": "ktec/ergodone"
}, },
@ -212,6 +212,15 @@
"gmmk/pro/iso": { "gmmk/pro/iso": {
"target": "gmmk/pro/rev1/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": { "handwired/ferris": {
"target": "ferris/0_1" "target": "ferris/0_1"
}, },
@ -221,6 +230,21 @@
"handwired/p1800fl": { "handwired/p1800fl": {
"target": "team0110/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": { "helix/pico/sc/back": {
"target": "helix/pico/sc" "target": "helix/pico/sc"
}, },
@ -263,14 +287,17 @@
"honeycomb": { "honeycomb": {
"target": "keyhive/honeycomb" "target": "keyhive/honeycomb"
}, },
"hub16": {
"target": "joshajohnson/hub16"
},
"hub20": {
"target": "joshajohnson/hub20"
},
"idb_60": { "idb_60": {
"target": "idb/idb_60", "target": "idb/idb_60"
"layouts": {
"LAYOUT": "LAYOUT_all"
}
}, },
"idobo": { "idobo": {
"target": "idobao/id75" "target": "idobao/id75/v1"
}, },
"jacky_studio/piggy60": { "jacky_studio/piggy60": {
"target": "jacky_studio/piggy60/rev1" "target": "jacky_studio/piggy60/rev1"
@ -288,35 +315,68 @@
"target": "jones/v03_1" "target": "jones/v03_1"
}, },
"kamigakushi": { "kamigakushi": {
"target": "jaykeeb/kamigakushi", "target": "jaykeeb/kamigakushi"
"layouts": {
"LAYOUT": "LAYOUT_65_ansi_blocker_tsangan"
}
}, },
"katana60": { "katana60": {
"target": "rominronin/katana60/rev1" "target": "rominronin/katana60/rev1"
}, },
"kbdfans/kbd67mkiirgb": { "kbdfans/kbd67mkiirgb": {
"target": "kbdfans/kbd67/mkiirgb", "target": "kbdfans/kbd67/mkiirgb"
"layouts": {
"LAYOUT": "LAYOUT_65_ansi_blocker"
}
}, },
"kbdfans/kbd67/mkiirgb": { "kbdfans/kbd67/mkiirgb": {
"target": "kbdfans/kbd67/mkiirgb/v1" "target": "kbdfans/kbd67/mkiirgb/v1"
}, },
"keebio/chocopad": {
"target": "keebio/chocopad/rev1"
},
"keebio/dsp40": { "keebio/dsp40": {
"target": "keebio/dsp40/rev1" "target": "keebio/dsp40/rev1"
}, },
"keycapsss/plaid_pad": { "keycapsss/plaid_pad": {
"target": "keycapsss/plaid_pad/rev1" "target": "keycapsss/plaid_pad/rev1"
}, },
"kira75": {
"target": "kira/kira75"
},
"kira80": {
"target": "kira/kira80"
},
"kudox": { "kudox": {
"target": "kudox/rev1" "target": "kumaokobo/kudox/rev1"
},
"kudox/columner": {
"target": "kumaokobo/kudox/columner"
},
"kudox/rev1": {
"target": "kumaokobo/kudox/rev1"
},
"kudox/rev2": {
"target": "kumaokobo/kudox/rev2"
},
"kudox/rev3": {
"target": "kumaokobo/kudox/rev3"
},
"kudox_full": {
"target": "kumaokobo/kudox_full/rev1"
},
"kudox_full/rev1": {
"target": "kumaokobo/kudox_full/rev1"
},
"kudox_game": {
"target": "kumaokobo/kudox_game/rev1"
},
"kudox_game/rev1": {
"target": "kumaokobo/kudox_game/rev1"
},
"kudox_game/rev2": {
"target": "kumaokobo/kudox_game/rev2"
}, },
"kyria": { "kyria": {
"target": "splitkb/kyria" "target": "splitkb/kyria"
}, },
"laser_ninja/pumpkin_pad": {
"target": "laser_ninja/pumpkinpad"
},
"lattice60": { "lattice60": {
"target": "keyhive/lattice60" "target": "keyhive/lattice60"
}, },
@ -395,6 +455,9 @@
"maartenwut/wonderland": { "maartenwut/wonderland": {
"target": "evyd13/wonderland" "target": "evyd13/wonderland"
}, },
"matchstickworks/southpad": {
"target": "matchstickworks/southpad/rev2/"
},
"matrix/m12og": { "matrix/m12og": {
"target": "matrix/m12og/rev1" "target": "matrix/m12og/rev1"
}, },
@ -405,7 +468,7 @@
"target": "mechlovin/adelais/rgb_led/rev1" "target": "mechlovin/adelais/rgb_led/rev1"
}, },
"mechlovin/adelais/standard_led": { "mechlovin/adelais/standard_led": {
"target": "mechlovin/adelais/standard_led/rev2" "target": "mechlovin/adelais/standard_led/arm/rev2"
}, },
"mechlovin/delphine": { "mechlovin/delphine": {
"target": "mechlovin/delphine/mono_led" "target": "mechlovin/delphine/mono_led"
@ -428,6 +491,15 @@
"minim": { "minim": {
"target": "matthewdias/minim" "target": "matthewdias/minim"
}, },
"mnk1800s": {
"target": "monokei/mnk1800s"
},
"mnk50": {
"target": "monokei/mnk50"
},
"mnk75": {
"target": "monokei/mnk75"
},
"model01": { "model01": {
"target": "keyboardio/model01" "target": "keyboardio/model01"
}, },
@ -440,14 +512,12 @@
"montsinger/rebound": { "montsinger/rebound": {
"target": "montsinger/rebound/rev1" "target": "montsinger/rebound/rev1"
}, },
"moonlander": {
"target": "zsa/moonlander"
},
"mschwingen/modelm": { "mschwingen/modelm": {
"target": "ibm/model_m/mschwingen" "target": "ibm/model_m/mschwingen"
}, },
"noxary/268_2": {
"layouts": {
"LAYOUT": "LAYOUT_65_ansi_blocker"
}
},
"oddball": { "oddball": {
"target": "oddball/v1" "target": "oddball/v1"
}, },
@ -464,24 +534,28 @@
"target": "pabile/p20/ver1" "target": "pabile/p20/ver1"
}, },
"pancake/feather": { "pancake/feather": {
"target": "spaceman/pancake/feather" "target": "spaceman/pancake/rev1/feather"
}, },
"pancake/promicro": { "pancake/promicro": {
"target": "spaceman/pancake/promicro" "target": "spaceman/pancake/rev1/promicro"
}, },
"peiorisboards/ixora": { "peiorisboards/ixora": {
"target": "coarse/ixora" "target": "coarse/ixora"
}, },
"percent/canoe": { "pico": {
"layouts": { "target": "kumaokobo/pico/65keys"
"LAYOUT_iso": "LAYOUT_65_iso_blocker" },
} "pico/65keys": {
"target": "kumaokobo/pico/65keys"
},
"pico/70keys": {
"target": "kumaokobo/pico/70keys"
}, },
"plaid": { "plaid": {
"target": "dm9records/plaid" "target": "dm9records/plaid"
}, },
"plain60": { "plain60": {
"target": "maartenwut/plain60" "target": "evyd13/plain60"
}, },
"ploopyco/trackball": { "ploopyco/trackball": {
"target": "ploopyco/trackball/rev1_005" "target": "ploopyco/trackball/rev1_005"
@ -489,21 +563,6 @@
"polilla": { "polilla": {
"target": "polilla/rev1" "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": { "primekb/prime_l": {
"target": "primekb/prime_l/v1" "target": "primekb/prime_l/v1"
}, },
@ -532,10 +591,13 @@
"target": "wilba_tech/rama_works_u80_a" "target": "wilba_tech/rama_works_u80_a"
}, },
"ramonimbao/herringbone": { "ramonimbao/herringbone": {
"target": "ramonimbao/herringbone/v1" "target": "rmi_kb/herringbone/v1"
}, },
"ramonimbao/mona": { "ramonimbao/mona": {
"target": "ramonimbao/mona/v1" "target": "rmi_kb/mona/v1"
},
"redox_w": {
"target": "redox/wireless"
}, },
"rgbkb/pan": { "rgbkb/pan": {
"target": "rgbkb/pan/rev1/32a" "target": "rgbkb/pan/rev1/32a"
@ -571,10 +633,10 @@
"target": "tkw/stoutgat/v1" "target": "tkw/stoutgat/v1"
}, },
"suihankey": { "suihankey": {
"target": "suihankey/split/alpha" "target": "kakunpc/suihankey/split/alpha"
}, },
"ta65": { "ta65": {
"target": "maartenwut/ta65" "target": "evyd13/ta65"
}, },
"tartan": { "tartan": {
"target": "dm9records/tartan" "target": "dm9records/tartan"
@ -592,16 +654,13 @@
"target": "matthewdias/txuu" "target": "matthewdias/txuu"
}, },
"underscore33": { "underscore33": {
"target": "underscore33/rev1" "target": "tominabox1/underscore33/rev1"
}, },
"vinta": { "vinta": {
"target": "coarse/vinta", "target": "coarse/vinta"
"layouts": {
"LAYOUT_67_ansi": "LAYOUT_65_ansi_blocker"
}
}, },
"wasdat": { "wasdat": {
"target": "maartenwut/wasdat" "target": "evyd13/wasdat"
}, },
"westfoxtrot/cypher": { "westfoxtrot/cypher": {
"target": "westfoxtrot/cypher/rev1" "target": "westfoxtrot/cypher/rev1"
@ -613,10 +672,10 @@
"target": "xiudi/xd002" "target": "xiudi/xd002"
}, },
"xd004": { "xd004": {
"target": "xiudi/xd004" "target": "xiudi/xd004/v1"
}, },
"xd60": { "xd60": {
"target": "xiudi/xd60" "target": "xiudi/xd60/rev2"
}, },
"xd68": { "xd68": {
"target": "xiudi/xd68" "target": "xiudi/xd68"
@ -808,6 +867,12 @@
"eggman": { "eggman": {
"target": "qpockets/eggman" "target": "qpockets/eggman"
}, },
"enter67": {
"target": "kezewa/enter67"
},
"enter80": {
"target": "kezewa/enter80"
},
"ergo42": { "ergo42": {
"target": "biacco42/ergo42" "target": "biacco42/ergo42"
}, },
@ -829,9 +894,15 @@
"espectro": { "espectro": {
"target": "mechkeys/espectro" "target": "mechkeys/espectro"
}, },
"eu_isolation": {
"target": "p3d/eu_isolation"
},
"felix": { "felix": {
"target": "unikeyboard/felix" "target": "unikeyboard/felix"
}, },
"flygone60/rev3": {
"target": "shandoncodes/flygone60/rev3"
},
"four_banger": { "four_banger": {
"target": "bpiphany/four_banger" "target": "bpiphany/four_banger"
}, },
@ -863,19 +934,22 @@
"target": "kagizaraya/halberd" "target": "kagizaraya/halberd"
}, },
"handwired/hillside/0_1": { "handwired/hillside/0_1": {
"target": "handwired/hillside/48" "target": "hillside/48/0_1"
}, },
"hecomi/alpha": { "hecomi/alpha": {
"target": "takashiski/hecomi/alpha" "target": "takashiski/hecomi/alpha"
}, },
"hfdkb/keyboard_sw/k83":{
"target": "inland/kb83"
},
"hid_liber": { "hid_liber": {
"target": "bpiphany/hid_liber" "target": "bpiphany/hid_liber"
}, },
"id67/default_rgb": { "id67/default_rgb": {
"target": "idobao/id67/default_rgb" "target": "idobao/id67"
}, },
"id67/rgb": { "id67/rgb": {
"target": "idobao/id67/rgb" "target": "idobao/id67"
}, },
"id80": { "id80": {
"target": "idobao/id80/v2/ansi" "target": "idobao/id80/v2/ansi"
@ -913,12 +987,33 @@
"kelowna/rgb64": { "kelowna/rgb64": {
"target": "weirdo/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"
}
"kmac": {
"target": "kbdmania/kmac"
}
"kmac_pad": {
"target": "kbdmania/kmac_pad"
}
"kprepublic/bm40hsrgb": {
"target": "kprepublic/bm40hsrgb/rev1"
},
"kprepublic/bm65hsrgb_iso": { "kprepublic/bm65hsrgb_iso": {
"target": "kprepublic/bm65hsrgb_iso/rev1" "target": "kprepublic/bm65hsrgb_iso/rev1"
}, },
"kprepublic/bm68hsrgb": { "kprepublic/bm68hsrgb": {
"target": "kprepublic/bm68hsrgb/rev1" "target": "kprepublic/bm68hsrgb/rev1"
}, },
"late9/rev1": {
"target": "rookiebwoy/late9/rev1"
},
"latin17rgb": { "latin17rgb": {
"target": "latincompass/latin17rgb" "target": "latincompass/latin17rgb"
}, },
@ -943,6 +1038,12 @@
"launchpad/rev1": { "launchpad/rev1": {
"target": "maple_computing/launchpad/rev1" "target": "maple_computing/launchpad/rev1"
}, },
"lefty": {
"target": "smoll/lefty/rev2"
},
"lefty/rev1": {
"target": "smoll/lefty/rev1"
},
"lck75": { "lck75": {
"target": "lyso1/lck75" "target": "lyso1/lck75"
}, },
@ -958,9 +1059,21 @@
"ls_60": { "ls_60": {
"target": "weirdo/ls_60" "target": "weirdo/ls_60"
}, },
"lpad": {
"target": "laneware/lpad"
},
"lw67": {
"target": "laneware/lw67"
},
"lw75": {
"target": "laneware/lw75"
},
"m3n3van": { "m3n3van": {
"target": "matthewdias/m3n3van" "target": "matthewdias/m3n3van"
}, },
"macro1": {
"target": "laneware/macro1"
},
"massdrop/thekey": { "massdrop/thekey": {
"target": "drop/thekey/v1" "target": "drop/thekey/v1"
}, },
@ -985,9 +1098,21 @@
"melody96": { "melody96": {
"target": "ymdk/melody96" "target": "ymdk/melody96"
}, },
"miniaxe": {
"target": "kagizaraya/miniaxe"
},
"minidox/rev1": { "minidox/rev1": {
"target": "maple_computing/minidox/rev1" "target": "maple_computing/minidox/rev1"
}, },
"mino/hotswap": {
"target": "shandoncodes/mino/hotswap"
},
"mino_plus/hotswap": {
"target": "shandoncodes/mino_plus/hotswap"
},
"mino_plus/soldered": {
"target": "shandoncodes/mino_plus/soldered"
},
"mio": { "mio": {
"target": "recompile_keys/mio" "target": "recompile_keys/mio"
}, },
@ -1042,6 +1167,9 @@
"nebula68b": { "nebula68b": {
"target": "spaceholdings/nebula68b" "target": "spaceholdings/nebula68b"
}, },
"neopad/rev1": {
"target": "rookiebwoy/neopad/rev1"
},
"niu_mini": { "niu_mini": {
"target": "kbdfans/niu_mini" "target": "kbdfans/niu_mini"
}, },
@ -1096,6 +1224,12 @@
"pursuit40": { "pursuit40": {
"target": "checkerboards/pursuit40" "target": "checkerboards/pursuit40"
}, },
"pw88": {
"target": "smoll/pw88"
},
"q4z": {
"target": "p3d/q4z"
},
"qaz": { "qaz": {
"target": "tominabox1/qaz" "target": "tominabox1/qaz"
}, },
@ -1105,6 +1239,9 @@
"rabbit_capture_plan": { "rabbit_capture_plan": {
"target": "kakunpc/rabbit_capture_plan" "target": "kakunpc/rabbit_capture_plan"
}, },
"raindrop": {
"target": "laneware/raindrop"
},
"ramonimbao/aelith": { "ramonimbao/aelith": {
"target": "rmi_kb/aelith" "target": "rmi_kb/aelith"
}, },
@ -1171,6 +1308,9 @@
"reviung61": { "reviung61": {
"target": "reviung/reviung61" "target": "reviung/reviung61"
}, },
"riot_pad": {
"target": "shandoncodes/riot_pad"
},
"runner3680/3x6": { "runner3680/3x6": {
"target": "omkbd/runner3680/3x6" "target": "omkbd/runner3680/3x6"
}, },
@ -1213,12 +1353,21 @@
"setta21": { "setta21": {
"target": "salicylic_acid3/setta21" "target": "salicylic_acid3/setta21"
}, },
"soda/mango": {
"target": "magic_force/mf17"
},
"soda/pocket": {
"target": "magic_force/mf34"
},
"space_space/rev1": { "space_space/rev1": {
"target": "qpockets/space_space/rev1" "target": "qpockets/space_space/rev1"
}, },
"space_space/rev2": { "space_space/rev2": {
"target": "qpockets/space_space/rev2" "target": "qpockets/space_space/rev2"
}, },
"spacey": {
"target": "p3d/spacey"
},
"spiderisland/winry25tc": { "spiderisland/winry25tc": {
"target": "winry/winry25tc" "target": "winry/winry25tc"
}, },
@ -1237,6 +1386,9 @@
"stella": { "stella": {
"target": "hnahkb/stella" "target": "hnahkb/stella"
}, },
"studiokestra/line_tkl": {
"target": "studiokestra/line_friends_tkl"
},
"suihankey/alpha": { "suihankey/alpha": {
"target": "kakunpc/suihankey/alpha" "target": "kakunpc/suihankey/alpha"
}, },
@ -1246,6 +1398,9 @@
"suihankey/split": { "suihankey/split": {
"target": "kakunpc/suihankey/split" "target": "kakunpc/suihankey/split"
}, },
"synapse": {
"target": "p3d/synapse"
},
"the_ruler": { "the_ruler": {
"target": "maple_computing/the_ruler" "target": "maple_computing/the_ruler"
}, },
@ -1265,7 +1420,10 @@
"target": "marksard/treadstone48/rev2" "target": "marksard/treadstone48/rev2"
}, },
"tronguylabs/m122_3270": { "tronguylabs/m122_3270": {
"target": "ibm/model_m_122/m122_3270" "target": "ibm/model_m_122/m122_3270/teensy"
},
"tw40": {
"target": "p3d/tw40"
}, },
"ua62": { "ua62": {
"target": "nacly/ua62" "target": "nacly/ua62"
@ -1285,6 +1443,9 @@
"vn66": { "vn66": {
"target": "hnahkb/vn66" "target": "hnahkb/vn66"
}, },
"w1_at": {
"target": "geonworks/w1_at"
},
"wallaby": { "wallaby": {
"target": "kkatano/wallaby" "target": "kkatano/wallaby"
}, },
@ -1319,7 +1480,7 @@
"target": "ydkb/yd68" "target": "ydkb/yd68"
}, },
"ymd75": { "ymd75": {
"target": "ymdk/ymd75" "target": "ymdk/ymd75/rev1"
}, },
"ymd96": { "ymd96": {
"target": "ymdk/ymd96" "target": "ymdk/ymd96"
@ -1333,6 +1494,12 @@
"yurei": { "yurei": {
"target": "kkatano/yurei" "target": "kkatano/yurei"
}, },
"z12": {
"target": "zigotica/z12"
},
"z34": {
"target": "zigotica/z34"
},
"zinc": { "zinc": {
"target": "25keys/zinc" "target": "25keys/zinc"
}, },
@ -1341,5 +1508,9 @@
}, },
"zinc/reva": { "zinc/reva": {
"target": "25keys/zinc/reva" "target": "25keys/zinc/reva"
},
// Moved during 2023 Q4 cycle
"ymdk/melody96": {
"target": "ymdk/melody96/soldered"
} }
} }

View File

@ -3,10 +3,25 @@
"$id": "qmk.definitions.v1", "$id": "qmk.definitions.v1",
"title": "Common definitions used across QMK's jsonschemas.", "title": "Common definitions used across QMK's jsonschemas.",
"type": "object", "type": "object",
"bcd_version": {
"type": "string",
"pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
},
"bit": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"boolean_array": { "boolean_array": {
"type": "object", "type": "object",
"additionalProperties": {"type": "boolean"} "additionalProperties": {"type": "boolean"}
}, },
"build_target": {
"oneOf": [
{"$ref": "#/keyboard_keymap_tuple"},
{"$ref": "#/json_file_path"}
]
},
"filename": { "filename": {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
@ -20,14 +35,56 @@
"type": "string", "type": "string",
"pattern": "^0x[0-9A-F]{4}$" "pattern": "^0x[0-9A-F]{4}$"
}, },
"bcd_version": { "json_file_path": {
"type": "string", "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", "type": "string",
"minLength": 1, "pattern": "^[0-9a-z][0-9a-z_/]*$"
"maxLength": 250 },
"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": { "layout_macro": {
"oneOf": [ "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": { "mcu_pin": {
"oneOf": [ "oneOf": [
{ {
@ -125,14 +139,14 @@
"type": "string", "type": "string",
"pattern": "^GP\\d{1,2}$" "pattern": "^GP\\d{1,2}$"
}, },
{ {"type": "integer"},
"type": "integer" {"type": "null"}
},
{
"type": "null"
}
] ]
}, },
"mcu_pin_array": {
"type": "array",
"items": {"$ref": "#/mcu_pin"}
},
"signed_decimal": { "signed_decimal": {
"type": "number" "type": "number"
}, },
@ -144,17 +158,22 @@
"minimum": -127, "minimum": -127,
"maximum": 127 "maximum": 127
}, },
"snake_case": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$"
},
"string_array": { "string_array": {
"type": "array", "type": "array",
"items": { "items": {"type": "string"}
"type": "string"
}
}, },
"string_object": { "string_object": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {"type": "string"}
"type": "string" },
} "text_identifier": {
"type": "string",
"minLength": 1,
"maxLength": 250
}, },
"unsigned_decimal": { "unsigned_decimal": {
"type": "number", "type": "number",
@ -168,10 +187,5 @@
"type": "integer", "type": "integer",
"minimum": 0, "minimum": 0,
"maximum": 255 "maximum": 255
},
"bit": {
"type": "integer",
"minimum": 0,
"maximum": 1
} }
} }

View File

@ -20,7 +20,15 @@
} }
} }
} }
} },
"dip_switch_config": {
"type": "object",
"properties": {
"pins": {
"$ref": "qmk.definitions.v1#/mcu_pin_array"
}
}
},
}, },
"type": "object", "type": "object",
"not": { "required": [ "vendorId", "productId" ] }, // reject via keys... "not": { "required": [ "vendorId", "productId" ] }, // reject via keys...
@ -35,7 +43,7 @@
}, },
"development_board": { "development_board": {
"type": "string", "type": "string",
"enum": ["promicro", "elite_c", "elite_pi", "proton_c", "kb2040", "promicro_rp2040", "blok", "michi", "bit_c_pro", "stemcell", "bluepill", "blackpill_f401", "blackpill_f411", "bonsai_c4", "helios", "liatris"] "enum": ["promicro", "elite_c", "elite_pi", "proton_c", "kb2040", "promicro_rp2040", "blok", "michi", "bit_c_pro", "stemcell", "bluepill", "blackpill_f401", "blackpill_f411", "bonsai_c4", "helios", "liatris", "imera"]
}, },
"pin_compatible": { "pin_compatible": {
"type": "string", "type": "string",
@ -71,6 +79,8 @@
"STM32F446", "STM32F446",
"STM32G431", "STM32G431",
"STM32G474", "STM32G474",
"STM32H723",
"STM32H733",
"STM32L412", "STM32L412",
"STM32L422", "STM32L422",
"STM32L432", "STM32L432",
@ -113,6 +123,14 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"default": {
"type": "object",
"additionalProperties": false,
"properties": {
"on": {"type": "boolean"},
"clicky": {"type": "boolean"}
}
},
"macro_beep": {"type": "boolean"}, "macro_beep": {"type": "boolean"},
"pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}, "pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"voices": {"type": "boolean"} "voices": {"type": "boolean"}
@ -126,6 +144,15 @@
"type": "string", "type": "string",
"enum": ["pwm", "software", "timer", "custom"] "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": {"type": "boolean"},
"breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}, "breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"levels": { "levels": {
@ -146,7 +173,7 @@
"properties": { "properties": {
"driver": { "driver": {
"type": "string", "type": "string",
"enum": ["BluefruitLE", "RN42", "custom"] "enum": ["bluefruit_le", "custom", "rn42"]
} }
} }
}, },
@ -174,6 +201,7 @@
"bootloader": { "bootloader": {
"type": "string", "type": "string",
"enum": [ "enum": [
"apm32-dfu",
"atmel-dfu", "atmel-dfu",
"bootloadhid", "bootloadhid",
"caterina", "caterina",
@ -242,9 +270,40 @@
"type": "array", "type": "array",
"items": {"$ref": "qmk.definitions.v1#/filename"} "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": { "eeprom": {
"properties": { "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": { "encoder": {
@ -253,7 +312,11 @@
"enabled": {"type": "boolean"} "enabled": {"type": "boolean"}
} }
}, },
"features": {"$ref": "qmk.definitions.v1#/boolean_array"}, "features": {
"$ref": "qmk.definitions.v1#/boolean_array",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" },
"not": { "required": [ "lto" ] }
},
"indicators": { "indicators": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -293,6 +356,7 @@
"additionalProperties": false, "additionalProperties": false,
"required": ["x", "y"], "required": ["x", "y"],
"properties": { "properties": {
"encoder": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"label": { "label": {
"type": "string", "type": "string",
"pattern": "^[^\\n]*$" "pattern": "^[^\\n]*$"
@ -367,10 +431,21 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": { "additionalProperties": {
"type": "boolean" "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"}, "driver": {"type": "string"},
"center_point": { "center_point": {
"type": "array", "type": "array",
@ -380,10 +455,12 @@
}, },
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}, "max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "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"}, "val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"speed_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": { "split_count": {
"type": "array", "type": "array",
"minItems": 2, "minItems": 2,
@ -418,10 +495,23 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": { "additionalProperties": {
"type": "boolean" "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"}, "driver": {"type": "string"},
"center_point": { "center_point": {
"type": "array", "type": "array",
@ -435,6 +525,10 @@
"sat_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "sat_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"speed_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": { "split_count": {
"type": "array", "type": "array",
"minItems": 2, "minItems": 2,
@ -470,11 +564,28 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
"additionalProperties": { "additionalProperties": {
"type": "boolean" "type": "boolean"
} }
}, },
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "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"}, "hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"layers": { "layers": {
"type": "object", "type": "object",
@ -491,6 +602,11 @@
} }
}, },
"led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "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"}, "max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"pin": { "pin": {
"$ref": "qmk.definitions.v1#/mcu_pin", "$ref": "qmk.definitions.v1#/mcu_pin",
@ -576,10 +692,6 @@
} }
} }
}, },
"matrix_grid": {
"type": "array",
"items": {"$ref": "qmk.definitions.v1#/mcu_pin"}
},
"matrix_pins": { "matrix_pins": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@ -599,6 +711,15 @@
} }
} }
}, },
"dip_switch": {
"type": "object",
"additionalProperties": false,
"properties": {
"right": {
"$ref": "#/definitions/dip_switch_config"
}
}
},
"encoder": { "encoder": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@ -608,9 +729,17 @@
} }
} }
}, },
"main": { "handedness": {
"type": "string", "type": "object",
"enum": ["eeprom", "left", "matrix_grid", "pin", "right"] "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_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"soft_serial_speed": { "soft_serial_speed": {
@ -626,10 +755,32 @@
"type": "string", "type": "string",
"enum": ["custom", "i2c", "serial", "serial_usart"] "enum": ["custom", "i2c", "serial", "serial_usart"]
}, },
"sync_matrix_state": {"type": "boolean"}, "sync": {
"sync_modifiers": {"type": "boolean"}, "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": {"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": { "usb_detect": {
@ -640,6 +791,16 @@
"polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"timeout": {"$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 +858,15 @@
"properties": { "properties": {
"keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}, "keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "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": { "qmk_lufa_bootloader": {

View File

@ -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",
},
}
}

View File

@ -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"
}
}
}
}

305
docs/ChangeLog/20230827.md Normal file
View File

@ -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))

336
docs/ChangeLog/20231126.md Normal file
View File

@ -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))

View File

@ -4,7 +4,7 @@
* [Building Your First Firmware](newbs_building_firmware.md) * [Building Your First Firmware](newbs_building_firmware.md)
* [Flashing Firmware](newbs_flashing.md) * [Flashing Firmware](newbs_flashing.md)
* [Getting Help/Support](support.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) * [Other Resources](newbs_learn_more_resources.md)
* [Syllabus](syllabus.md) * [Syllabus](syllabus.md)
@ -80,6 +80,7 @@
* [Caps Word](feature_caps_word.md) * [Caps Word](feature_caps_word.md)
* [Combos](feature_combo.md) * [Combos](feature_combo.md)
* [Debounce API](feature_debounce_type.md) * [Debounce API](feature_debounce_type.md)
* [Digitizer](feature_digitizer.md)
* [EEPROM](feature_eeprom.md) * [EEPROM](feature_eeprom.md)
* [Key Lock](feature_key_lock.md) * [Key Lock](feature_key_lock.md)
* [Key Overrides](feature_key_overrides.md) * [Key Overrides](feature_key_overrides.md)
@ -115,7 +116,6 @@
* [Bootmagic Lite](feature_bootmagic.md) * [Bootmagic Lite](feature_bootmagic.md)
* [Converters](feature_converters.md) * [Converters](feature_converters.md)
* [Custom Matrix](custom_matrix.md) * [Custom Matrix](custom_matrix.md)
* [Digitizer](feature_digitizer.md)
* [DIP Switch](feature_dip_switch.md) * [DIP Switch](feature_dip_switch.md)
* [Encoders](feature_encoders.md) * [Encoders](feature_encoders.md)
* [Haptic Feedback](feature_haptic_feedback.md) * [Haptic Feedback](feature_haptic_feedback.md)
@ -126,7 +126,6 @@
* [PS/2 Mouse](feature_ps2_mouse.md) * [PS/2 Mouse](feature_ps2_mouse.md)
* [Split Keyboard](feature_split_keyboard.md) * [Split Keyboard](feature_split_keyboard.md)
* [Stenography](feature_stenography.md) * [Stenography](feature_stenography.md)
* [Velocikey](feature_velocikey.md)
* Keyboard Building * Keyboard Building
* [Easy Maker for One Offs](easy_maker.md) * [Easy Maker for One Offs](easy_maker.md)
@ -139,7 +138,7 @@
* Breaking Changes * Breaking Changes
* [Overview](breaking_changes.md) * [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.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) * [Past Breaking Changes](breaking_changes_history.md)
* C Development * C Development
@ -148,6 +147,7 @@
* [Compatible Microcontrollers](compatible_microcontrollers.md) * [Compatible Microcontrollers](compatible_microcontrollers.md)
* [Drivers](hardware_drivers.md) * [Drivers](hardware_drivers.md)
* [ADC Driver](adc_driver.md) * [ADC Driver](adc_driver.md)
* [APA102 Driver](apa102_driver.md)
* [Audio Driver](audio_driver.md) * [Audio Driver](audio_driver.md)
* [I2C Driver](i2c_driver.md) * [I2C Driver](i2c_driver.md)
* [SPI Driver](spi_driver.md) * [SPI Driver](spi_driver.md)

View File

@ -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`: To use this driver, add the following to your `rules.mk`:
```make ```make
SRC += analog.c ANALOG_DRIVER_REQUIRED = yes
``` ```
Then place this include at the top of your code: Then place this include at the top of your code:

49
docs/apa102_driver.md Normal file
View File

@ -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.

View File

@ -116,19 +116,32 @@ Additionally, in the board config, you'll want to make changes to enable the DAC
| Define | Defaults | Description | | Define | Defaults | Description |
| -------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AUDIO_DAC_SAMPLE_MAX` | `4095U` | Highest value allowed. Lower value means lower volume. And 4095U is the upper limit, since this is limited to a 12 bit value. Only effects non-pregenerated samples. | | `AUDIO_DAC_SAMPLE_MAX` | `4095U` | Highest value allowed. Lower value means lower volume. And 4095U is the upper limit, since this is limited to a 12 bit value. Only effects non-pregenerated samples. |
| `AUDIO_DAC_OFF_VALUE` | `AUDIO_DAC_SAMPLE_MAX / 2` | The value of the DAC when notplaying anything. Some setups may require a high (`AUDIO_DAC_SAMPLE_MAX`) or low (`0`) value here. | | `AUDIO_DAC_OFF_VALUE` | `AUDIO_DAC_SAMPLE_MAX / 2` | The value of the DAC when not playing anything. Some setups may require a high (`AUDIO_DAC_SAMPLE_MAX`) or low (`0`) value here. |
| `AUDIO_MAX_SIMULTANEOUS_TONES` | __see next table__ | The number of tones that can be played simultaneously. A value that is too high may freeze the controller or glitch out when too many tones are being played. | | `AUDIO_MAX_SIMULTANEOUS_TONES` | __see next table__ | The number of tones that can be played simultaneously. A value that is too high may freeze the controller or glitch out when too many tones are being played. |
| `AUDIO_DAC_SAMPLE_RATE` | __see next table__ | Effective bit rate of the DAC (in hertz), higher limits simultaneous tones, and lower sacrifices quality. | | `AUDIO_DAC_SAMPLE_RATE` | __see next table__ | Effective bit rate of the DAC (in hertz), higher limits simultaneous tones, and lower sacrifices quality. |
| `AUDIO_DAC_BUFFER_SIZE` | __see next table__ | Number of samples generated every refill. Too few may cause excessive CPU load; too many may cause freezes, RAM or flash exhaustion or lags during matrix scanning. |
There are a number of predefined quality settings that you can use, with "sane minimum" being the default. You can use custom values by simply defining the sample rate and number of simultaneous tones, instead of using one of the listed presets. There are a number of predefined quality settings that you can use, with "sane minimum" being the default. You can use custom values by simply defining the sample rate, number of simultaneous tones and buffer size, instead of using one of the listed presets.
| Define | Sample Rate | Simultaneous tones | | Define | Sample Rate | Simultaneous tones | Buffer size |
| --------------------------------- | ----------- | ------------------- | | --------------------------------- | ----------- | ------------------- | ----------- |
| `AUDIO_DAC_QUALITY_VERY_LOW` | `11025U` | `8` | | `AUDIO_DAC_QUALITY_VERY_LOW` | `11025U` | `8` | `64U` |
| `AUDIO_DAC_QUALITY_LOW` | `22040U` | `4` | | `AUDIO_DAC_QUALITY_LOW` | `22050U` | `4` | `128U` |
| `AUDIO_DAC_QUALITY_HIGH` | `44100U` | `2` | | `AUDIO_DAC_QUALITY_HIGH` | `44100U` | `2` | `256U` |
| `AUDIO_DAC_QUALITY_VERY_HIGH` | `88200U` | `1` | | `AUDIO_DAC_QUALITY_VERY_HIGH` | `88200U` | `1` | `256U` |
| `AUDIO_DAC_QUALITY_SANE_MINIMUM` | `16384U` | `8` | | `AUDIO_DAC_QUALITY_SANE_MINIMUM` | `16384U` | `8` | `64U` |
#### Notes on buffer size :id=buffer-size
By default, the buffer size attempts to keep to these constraints:
* The interval between buffer refills can't be too short, since the microcontroller would then only be servicing buffer refills and would freeze up.
* On the additive driver, the interval between buffer refills can't be too long, since matrix scanning would suffer lengthy pauses every so often, which would delay key presses or releases or lose some short taps altogether.
* The interval between buffer refills is kept to a minimum, which allows notes to stop as soon as possible after they should.
* For greater compatibility, the buffer size should be a power of 2.
* The buffer size being too large causes resource exhaustion leading to build failures or freezing at runtime: RAM usage (on the additive driver) or flash usage (on the basic driver).
You can lower the buffer size if you need a bit more space in your firmware, or raise it if your keyboard freezes up.
```c ```c
@ -186,6 +199,11 @@ with all this information, the configuration would contain these lines:
ChibiOS uses GPIOv1 for the F103, which only knows of one alternate function. ChibiOS uses GPIOv1 for the F103, which only knows of one alternate function.
On 'larger' STM32s, GPIOv2 or GPIOv3 are used; with them it is also necessary to configure `AUDIO_PWM_PAL_MODE` to the correct alternate function for the selected pin, timer and timer-channel. On 'larger' STM32s, GPIOv2 or GPIOv3 are used; with them it is also necessary to configure `AUDIO_PWM_PAL_MODE` to the correct alternate function for the selected pin, timer and timer-channel.
You can also use the Complementary output (`TIMx_CHyN`) for PWM on supported controllers. To enable this functionality, you will need to make the following changes:
```c
// config.h:
#define AUDIO_PWM_COMPLEMENTARY_OUTPUT
```
### PWM software :id=pwm-software ### PWM software :id=pwm-software

View File

@ -10,25 +10,25 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
## What has been included in past Breaking Changes? ## 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 May 28](ChangeLog/20230528.md)
* [2023 Feb 26](ChangeLog/20230226.md)
* [2022 Nov 26](ChangeLog/20221126.md)
* [Older Breaking Changes](breaking_changes_history.md) * [Older Breaking Changes](breaking_changes_history.md)
## When is the next Breaking Change? ## 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 ### 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 Nov 26 - `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. * 2024 Jan 28 - `develop` closed to new PRs.
* 2023 Jul 30 - Call for testers. * 2024 Jan 28 - Call for testers.
* 2023 Aug 13 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes * 2024 Feb 4 - 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. * 2024 Feb 18 - `develop` is locked, only critical bugfix PRs merged.
* 2023 Aug 25 - `master` is locked, no PRs merged. * 2024 Feb 22 - `master` is locked, no PRs merged.
* 2023 Aug 27 - Merge `develop` to `master`. * 2024 Feb 25 - Merge `develop` to `master`.
* 2023 Aug 27 - `master` is unlocked. PRs can be merged again. * 2024 Feb 25 - `master` is unlocked. PRs can be merged again.
## What changes will be included? ## What changes will be included?
@ -48,7 +48,7 @@ Criteria for acceptance:
Strongly suggested: Strongly suggested:
* The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20230827`. * The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20240225`.
* This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PRs ID. * 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. * One strong recommendation that the ChangeLog document matches the PR description on GitHub, so as to ensure traceability.

View File

@ -2,6 +2,8 @@
This page links to all previous changelogs from the QMK Breaking Changes process. 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 May 28](ChangeLog/20230528.md) - version 0.21.0
* [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0 * [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0
* [2022 Nov 26](ChangeLog/20221126.md) - version 0.19.0 * [2022 Nov 26](ChangeLog/20221126.md) - version 0.19.0

View File

@ -2,11 +2,11 @@
## Overview :id=overview ## 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 ### 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 ### 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 ### 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 python3 -m pip install qmk

View File

@ -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 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` ## `qmk new-keyboard`
This command creates a new keyboard based on available templates. 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 <keyboard>:<keymap>, 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 <keyboard>:<keymap>, 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 # Developer Commands
## `qmk format-text` ## `qmk format-text`

View File

@ -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. 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 # 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. 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. You should never use the format operator (`%`) directly, always pass values as arguments.
### Logging (`cli.log`) ### 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 <subcommand>` the default log level will be set to `DEBUG`. The default log level is `INFO`. If the user runs `qmk -v <subcommand>` the default log level will be set to `DEBUG`.

View File

@ -8,8 +8,8 @@ Most of our style is pretty easy to pick up on, but right now it's not entirely
* Closing Brace: Lined up with the first character of the statement that opens the block * Closing Brace: Lined up with the first character of the statement that opens the block
* Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line. * Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
* Optional Braces: Always include optional braces. * Optional Braces: Always include optional braces.
* Good: if (condition) { return false; } * Good: `if (condition) { return false; }`
* Bad: if (condition) return false; * Bad: `if (condition) return false;`
* We encourage use of C style comments: `/* */` * We encourage use of C style comments: `/* */`
* Think of them as a story describing the feature * Think of them as a story describing the feature
* Use them liberally to explain why particular decisions were made. * Use them liberally to explain why particular decisions were made.

View File

@ -317,7 +317,7 @@ At the time of this writing our tests are not very comprehensive. Looking at the
## Integration Tests ## 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 ## Unit Tests

View File

@ -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) * [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html) * [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.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) * [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L422](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) * [STM32L432](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)

View File

@ -223,7 +223,7 @@ If you define these options you will enable the associated feature, which may in
* Adds ability to [blink](feature_rgblight.md?id=lighting-layer-blink) a lighting layer for a specified number of milliseconds (e.g. to acknowledge an action). * Adds ability to [blink](feature_rgblight.md?id=lighting-layer-blink) a lighting layer for a specified number of milliseconds (e.g. to acknowledge an action).
* `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF` * `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF`
* If defined, then [lighting layers](feature_rgblight?id=overriding-rgb-lighting-onoff-status) will be shown even if RGB Light is off. * If defined, then [lighting layers](feature_rgblight?id=overriding-rgb-lighting-onoff-status) will be shown even if RGB Light is off.
* `#define RGBLED_NUM 12` * `#define RGBLIGHT_LED_COUNT 12`
* number of LEDs * number of LEDs
* `#define RGBLIGHT_SPLIT` * `#define RGBLIGHT_SPLIT`
* Needed if both halves of the board have RGB LEDs wired directly to the RGB output pin on the controllers instead of passing the output of the left half to the input of the right half * Needed if both halves of the board have RGB LEDs wired directly to the RGB output pin on the controllers instead of passing the output of the left half to the input of the right half
@ -275,7 +275,7 @@ There are a few different ways to set handedness for split keyboards (listed in
* For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses. * For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
* `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>` * `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>`
* The handedness is determined by using the intersection of the keyswitches in the key matrix, which does not exist. Normally, when this intersection is shorted (level low), it is considered left. If you define `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT`, it is determined to be right when the level is low. * The handedness is determined by using the intersection of the keyswitches in the key matrix, which does not exist. Normally, when this intersection is shorted (level low), it is considered right. If you define `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_LEFT`, it is determined to be left when the level is low.
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` and `SPLIT_HAND_MATRIX_GRID` are not defined) * `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` and `SPLIT_HAND_MATRIX_GRID` are not defined)
* Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves. * Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves.
@ -439,7 +439,7 @@ Use these to enable or disable building certain features. The more you have enab
* `UNICODE_ENABLE` * `UNICODE_ENABLE`
* Unicode * Unicode
* `BLUETOOTH_ENABLE` * `BLUETOOTH_ENABLE`
* Current options are BluefruitLE, RN42 * Current options are bluefruit_le, rn42
* `SPLIT_KEYBOARD` * `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 * 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` * `CUSTOM_MATRIX`

View File

@ -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! 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. 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`. 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`. 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. 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.
@ -63,12 +63,14 @@ Most of our style is pretty easy to pick up on. If you are familiar with either
We have a few different types of changes in QMK, each requiring a different level of rigor. We'd like you to keep the following guidelines in mind no matter what type of change you're making. We have a few different types of changes in QMK, each requiring a different level of rigor. We'd like you to keep the following guidelines in mind no matter what type of change you're making.
* **Before you contribute:** Please make sure your fork is up to date with the upstream `qmk_firmware` repo. This will help minimize CI failures that may not occur for you when compiling locally.
* Separate PRs into logical units. For example, do not submit one PR covering two separate features, instead submit a separate PR for each feature. * 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. * Check for unnecessary whitespace with `git diff --check` before committing.
* Make sure your code change actually compiles. * 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. * Keyboards: Make sure that `make keyboard:all` does not return any errors.
* Core: Make sure that `make 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: * 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:
``` ```
@ -79,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. 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
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)! 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)!
@ -113,16 +113,6 @@ or if you only have Python 3 installed:
and navigating to `http://localhost:8936/`. 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
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. 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.
@ -130,7 +120,7 @@ Keyboards are the raison d'être for QMK. Some keyboards are community maintaine
We also ask that you follow these guidelines: We also ask that you follow these guidelines:
* Write a `readme.md` using [the template](documentation_templates.md). * 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. * 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/<kb1>/<kb2>/<kb2>.[ch]` * Name `.c`/`.h` file after the immediate parent folder, eg `/keyboards/<kb1>/<kb2>/<kb2>.[ch]`
* Do not include `Makefile`s in your keyboard folder (they're no longer used) * Do not include `Makefile`s in your keyboard folder (they're no longer used)

View File

@ -119,11 +119,11 @@ void keyboard_pre_init_user(void) {
// Call the keyboard pre init code. // Call the keyboard pre init code.
// Set our LED pins as output // Set our LED pins as output
setPinOutput(B0); gpio_set_pin_output(B0);
setPinOutput(B1); gpio_set_pin_output(B1);
setPinOutput(B2); gpio_set_pin_output(B2);
setPinOutput(B3); gpio_set_pin_output(B3);
setPinOutput(B4); gpio_set_pin_output(B4);
} }
``` ```
@ -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)` * 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)` * 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 # 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. 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.

View File

@ -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: The final piece of the puzzle is providing your new option to the build system. This is done by generating two files:
* `.build/obj_<keyboard>/src/info_config.h` * `.build/obj_<keyboard>_<keymap>/src/info_config.h`
* `.build/obj_<keyboard>/src/rules.mk` * `.build/obj_<keyboard>_<keymap>/src/rules.mk`
These two files are generated by the code here: These two files are generated by the code here:

View File

@ -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_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 `#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` | <https://www.adafruit.com/product/1897>
!> There's no way to determine if there is an SPI EEPROM actually responding. Generally, this will result in reads of nothing but zero. !> 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 ## 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 `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_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_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_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 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 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. !> 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_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_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 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. `#define BACKING_STORE_WRITE_SIZE` | `2` | The write width used whenever a write is performed on the external flash peripheral.

View File

@ -133,7 +133,17 @@ groups in the below fallback switch.
### NO_AUTO_SHIFT_SPECIAL (simple define) ### NO_AUTO_SHIFT_SPECIAL (simple define)
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, 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) ### 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. 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 ### 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`: 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) { bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
# ifndef NO_AUTO_SHIFT_ALPHA # ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z: case AUTO_SHIFT_ALPHA:
# endif # endif
# ifndef NO_AUTO_SHIFT_NUMERIC # ifndef NO_AUTO_SHIFT_NUMERIC
case KC_1 ... KC_0: case AUTO_SHIFT_NUMERIC:
# endif # endif
# ifndef NO_AUTO_SHIFT_SPECIAL # ifndef NO_AUTO_SHIFT_SPECIAL
# ifndef NO_AUTO_SHIFT_TAB
case KC_TAB: case KC_TAB:
case KC_MINUS ... KC_SLASH: # endif
case KC_NONUS_BACKSLASH: # ifndef NO_AUTO_SHIFT_SYMBOLS
case AUTO_SHIFT_SYMBOLS:
# endif
# endif
# ifdef AUTO_SHIFT_ENTER
case KC_ENT:
# endif # endif
return true; return true;
} }
@ -192,6 +212,25 @@ Enables keyrepeat.
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded. 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 ## Custom Shifted Values
Especially on small keyboards, the default shifted value for many keys is not 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 #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 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. 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. 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 ### Retro Shift and Tap Hold Configurations
Tap Hold Configurations work a little differently when using Retro Shift. Tap Hold Configurations work a little differently when using Retro Shift.

View File

@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
### Apply Autocorrect ### 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 #### 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); float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
#endif #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 #ifdef AUDIO_ENABLE
PLAY_SONG(autocorrect_song); PLAY_SONG(autocorrect_song);
#endif #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. ?> 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`: You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
```c ```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 #ifdef OLED_ENABLE
oled_write_P(PSTR("Auto-corrected"), false); oled_write_P(PSTR("Auto-corrected"), false);
#endif
#ifdef CONSOLE_ENABLE
printf("'%s' was corrected to '%s'\n", typo, correct);
#endif #endif
return true; return true;
} }

View File

@ -1,12 +1,12 @@
# Backlighting :id=backlighting # 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. 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 ```make
BACKLIGHT_ENABLE = yes BACKLIGHT_ENABLE = yes
@ -14,186 +14,95 @@ BACKLIGHT_ENABLE = yes
## Keycodes :id=keycodes ## 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 | ## Basic Configuration :id=basic-configuration
|---------------------------------|-----------|-------------------------------------|
| `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 |
## Functions :id=functions Add the following to your `config.h`:
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`:
|Define |Default |Description | |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_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_CAPS_LOCK` |*Not defined* |Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported | |`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported |
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds | |`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_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_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_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`. 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*. 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. 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`:
### AVR Driver :id=avr-driver ```c
#define BACKLIGHT_ON_STATE 0
The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
```make
BACKLIGHT_DRIVER = pwm
``` ```
#### Caveats :id=avr-caveats ### Multiple Backlight Pins :id=multiple-backlight-pins
On AVR boards, QMK automatically decides which driver to use according to the following table:
|Backlight Pin|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
|-------------|-------------|----------|-------------|-------------|---------|-----------|
|`B1` | | | | | |Timer 1 |
|`B2` | | | | | |Timer 1 |
|`B5` |Timer 1 | |Timer 1 | | | |
|`B6` |Timer 1 | |Timer 1 | | | |
|`B7` |Timer 1 |Timer 1 |Timer 1 |Timer 1 | | |
|`C4` |Timer 3 | | | | | |
|`C5` |Timer 3 |Timer 1 | |Timer 1 | | |
|`C6` |Timer 3 |Timer 1 |Timer 3 |Timer 1 | | |
|`D4` | | | | |Timer 1 | |
|`D5` | | | | |Timer 1 | |
All other pins will use timer-assisted software PWM:
|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 |
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.
#### Hardware PWM Implementation :id=hardware-pwm-implementation
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.
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.
#### Timer Assisted PWM Implementation :id=timer-assisted-implementation
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.
The breathing effect is the same as in the hardware PWM implementation.
### ARM Driver :id=arm-configuration
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:
```make
BACKLIGHT_DRIVER = pwm
```
#### ChibiOS Configuration :id=arm-configuration
The following `#define`s apply only to ARM-based keyboards:
|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|
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.
#### Caveats :id=arm-caveats
Currently only hardware PWM is supported, not timer assisted, and does not provide automatic configuration.
### Software PWM Driver :id=software-pwm-driver
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`:
```make
BACKLIGHT_DRIVER = software
```
#### 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). 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. 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. 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 activate multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`: To configure multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
```c ```c
#define BACKLIGHT_PINS { F5, B2 } #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.
### PWM Driver :id=pwm-driver
This is the default backlight driver, which leverages the hardware PWM output capability of the microcontroller.
```make
BACKLIGHT_DRIVER = pwm
```
### 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 ### 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 this simple API provided by QMK. To enable, add this to your `rules.mk`: 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 ```make
BACKLIGHT_DRIVER = custom BACKLIGHT_DRIVER = custom
``` ```
Then implement any of these hooks:
```c ```c
void backlight_init_ports(void) { void backlight_init_ports(void) {
// Optional - runs on startup // Optional - runs on startup
@ -211,10 +120,190 @@ void backlight_task(void) {
} }
``` ```
## AVR Configuration :id=avr-configuration
### PWM Driver :id=avr-pwm-driver
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|
|-------------|-------------|----------|-------------|-------------|---------|-----------|
|`B1` | | | | | |Timer 1 |
|`B2` | | | | | |Timer 1 |
|`B5` |Timer 1 | |Timer 1 | | | |
|`B6` |Timer 1 | |Timer 1 | | | |
|`B7` |Timer 1 |Timer 1 |Timer 1 |Timer 1 | | |
|`C4` |Timer 3 | | | | | |
|`C5` |Timer 3 |Timer 1 | |Timer 1 | | |
|`C6` |Timer 3 |Timer 1 |Timer 3 |Timer 1 | | |
|`D4` | | | | |Timer 1 | |
|`D5` | | | | |Timer 1 | |
### Timer Driver :id=avr-timer-driver
Any GPIO pin can be used with this driver. The following table describes the supported timers:
|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
|-------------|----------|-------------|-------------|---------|-----------|
|Timers 1 & 3 |Timer 1 |Timers 1 & 3 |Timer 1 |Timer 1 |Timer 1 |
The following `#define`s apply only to the `timer` driver:
|Define |Default|Description |
|-----------------------|-------|----------------|
|`BACKLIGHT_PWM_TIMER` |`1` |The timer to use|
Note that the choice of timer may conflict with the [Audio](feature_audio.md) feature.
## ChibiOS/ARM Configuration :id=arm-configuration
### PWM Driver :id=arm-pwm-driver
Depending on the ChibiOS board configuration, you may need to enable PWM at the keyboard level. For STM32, this would look like:
`halconf.h`:
```c
#define HAL_USE_PWM TRUE
```
`mcuconf.h`:
```c
#undef STM32_PWM_USE_TIM4
#define STM32_PWM_USE_TIM4 TRUE
```
The following `#define`s apply only to the `pwm` driver:
|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
```
The following `#define`s apply only to the `timer` driver:
|Define |Default |Description |
|----------------------|--------|----------------|
|`BACKLIGHT_GPT_DRIVER`|`GPTD15`|The timer to use|
## Example Schematic ## Example Schematic
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.
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. 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. 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. 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) ![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)
## API :id=api
### `void backlight_toggle(void)` :id=api-backlight-toggle
Toggle the backlight on or off.
---
### `void backlight_enable(void)` :id=api-backlight-enable
Turn the backlight on.
---
### `void backlight_disable(void)` :id=api-backlight-disable
Turn the backlight off.
---
### `void backlight_step(void)` :id=api-backlight-step
Cycle through backlight levels.
---
### `void backlight_increase(void)` :id=api-backlight-increase
Increase the backlight level.
---
### `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.

View File

@ -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. 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| |Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
|----------------------------------------------------------------|--------------------|---------------|--------------------------------|--------------| |----------------------------------------------------------------|--------------------|---------------|---------------------------------|--------------|
|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = RN42` |RN-42 | |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 | |[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = bluefruit_le`|nRF51822 |
Not Supported Yet but possible: 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) * [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 ```make
BLUETOOTH_ENABLE = yes BLUETOOTH_ENABLE = yes
BLUETOOTH_DRIVER = BluefruitLE # or RN42 BLUETOOTH_DRIVER = bluefruit_le # or rn42
``` ```
## Bluetooth Keycodes ## Bluetooth Keycodes

View File

@ -345,10 +345,9 @@ is not set, all other layers will reference themselves.
} }
return layer; // important if default is not in case. 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 ```c
COMBO_REF_LAYER(_DVORAK, _QWERTY) COMBO_REF_LAYER(_DVORAK, _QWERTY)

View File

@ -1,12 +1,10 @@
# Converters # 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 The following converters are available at this time:
Currently the following converters are available:
| From | To | | From | To |
|------------|-------------------| |------------|-------------------|
@ -21,6 +19,7 @@ Currently the following converters are available:
| `promicro` | `elite_pi` | | `promicro` | `elite_pi` |
| `promicro` | `helios` | | `promicro` | `helios` |
| `promicro` | `liatris` | | `promicro` | `liatris` |
| `promicro` | `imera` |
| `promicro` | `michi` | | `promicro` | `michi` |
| `elite_c` | `stemcell` | | `elite_c` | `stemcell` |
| `elite_c` | `rp2040_ce` | | `elite_c` | `rp2040_ce` |
@ -28,14 +27,10 @@ Currently the following converters are available:
| `elite_c` | `helios` | | `elite_c` | `helios` |
| `elite_c` | `liatris` | | `elite_c` | `liatris` |
See below for more in depth information on each converter.
## Overview ## Overview
Each converter category is broken down by its declared `pin compatibility`. 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=<target>` to your compile/flash command. For example:
This ensures that only valid combinations are attempted.
You can generate the firmware by appending `-e CONVERT_TO=<target>` to your compile/flash command. For example:
```sh ```sh
qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c
@ -59,14 +54,12 @@ Once a converter is enabled, it exposes the `CONVERT_TO_<target_uppercase>` flag
### Pin Compatibility ### 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`. 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:
Currently the following pin compatibility interfaces are defined: | Pin Compatibility | Notes |
|-------------------|-----------------------------------|
| Pinout | Notes | | `promicro` | Includes RX/TX LEDs |
|------------|-----------------------------------| | `elite_c` | Includes bottom row pins, no LEDs |
| `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`: To declare the base for conversions, add this line to your keyboard's `rules.mk`:
@ -90,6 +83,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` | | [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
| [Liatris](https://splitkb.com/products/liatris) | `liatris` | | [Liatris](https://splitkb.com/products/liatris) | `liatris` |
| [Imera](https://splitkb.com/products/imera) | `imera` |
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` | | [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
Converter summary: Converter summary:
@ -107,6 +101,7 @@ Converter summary:
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` | | `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` | | `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
| `imera` | `-e CONVERT_TO=imera` | `CONVERT_TO=imera` | `#ifdef CONVERT_TO_IMERA` |
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` | | `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
### Proton C :id=proton_c ### Proton C :id=proton_c
@ -140,7 +135,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 ### 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 ### STeMCell :id=stemcell
@ -150,9 +145,7 @@ There are two versions of STeMCell available, with different pinouts:
- v2.0.0 (pre-release v1.0.1, v1.0.2) - v2.0.0 (pre-release v1.0.1, v1.0.2)
Default official firmware only supports v2.0.0 STeMCell. 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. 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:
The following additional flags has to be used while compiling, based on the pin used for split communication.
| Split Pin | Compile flags | | Split Pin | Compile flags |
|-----------|---------------| |-----------|---------------|
@ -173,11 +166,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 ### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
Feature set currently identical to [Adafruit KB2040](#kb2040). 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.
Enables VBUS detection by default for superior split keyboard support.
For more information, refer to the [RP2040 Community Edition](platformdev_rp2040.md#rp2040_ce) docs.
## Elite-C ## Elite-C
@ -202,8 +192,8 @@ Converter summary:
### STeMCell :id=stemcell_elite ### 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 ### 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.

View File

@ -20,6 +20,27 @@ or
#define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs #define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs
``` ```
## DIP Switch map :id=dip-switch-map
DIP Switch mapping may be added to your `keymap.c`, which replicates the normal keyswitch functionality, but with dip switches. Add this to your keymap's `rules.mk`:
```make
DIP_SWITCH_MAP_ENABLE = yes
```
Your `keymap.c` will then need a dip switch mapping defined (for two dip switches):
```c
#if defined(DIP_SWITCH_MAP_ENABLE)
const uint16_t PROGMEM dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES] = {
DIP_SWITCH_OFF_ON(DF(0), DF(1)),
DIP_SWITCH_OFF_ON(EC_NORM, EC_SWAP)
};
#endif
```
?> This should only be enabled at the keymap level.
## Callbacks ## Callbacks
The callback functions can be inserted into your `<keyboard>.c`: The callback functions can be inserted into your `<keyboard>.c`:

View File

@ -82,10 +82,10 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
```c ```c
#if defined(ENCODER_MAP_ENABLE) #if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { 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) }, [0] = { 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) }, [1] = { 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) }, [2] = { 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) }, [3] = { ENCODER_CCW_CW(RGB_RMOD, RGB_MOD), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) },
}; };
#endif #endif
``` ```

View File

@ -4,11 +4,12 @@
The following options are currently available for haptic feedback in `rules.mk`: The following options are currently available for haptic feedback in `rules.mk`:
``` ```make
HAPTIC_ENABLE = yes HAPTIC_ENABLE = yes
HAPTIC_DRIVER += DRV2605L HAPTIC_DRIVER = drv2605l
HAPTIC_DRIVER += SOLENOID # or
HAPTIC_DRIVER = solenoid
``` ```
The following `config.h` settings are available for all types of haptic feedback: 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. 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.
``` ```c
#define FB_ERM_LRA 0 #define DRV2605L_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 DRV2605L_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 */ #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. */ /* Please refer to your datasheet for the optimal setting for your specific motor. */
#define RATED_VOLTAGE 3 #define DRV2605L_RATED_VOLTAGE 3
#define V_PEAK 5 #define DRV2605L_V_PEAK 5
``` ```
##### LRA ##### 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. 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.
``` ```c
#define FB_ERM_LRA 1 #define DRV2605L_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 DRV2605L_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 */ #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. */ /* Please refer to your datasheet for the optimal setting for your specific motor. */
#define RATED_VOLTAGE 2 #define DRV2605L_RATED_VOLTAGE 2
#define V_PEAK 2.8 #define DRV2605L_V_PEAK 2.8
#define V_RMS 2.0 #define DRV2605L_V_RMS 2.0
#define V_PEAK 2.1 #define DRV2605L_V_PEAK 2.1
#define F_LRA 205 /* resonance freq */ #define DRV2605L_F_LRA 205 /* resonance freq */
``` ```
#### DRV2605L waveform library #### DRV2605L waveform library
@ -170,13 +171,13 @@ List of waveform sequences from the datasheet:
| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | | | 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
### Optional DRV2605L defines ### Optional DRV2605L defines
``` ```c
#define DRV_GREETING *sequence name or number* #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: If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
``` ```c
#define DRV_MODE_DEFAULT *sequence name or number* #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. 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.

View File

@ -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. 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. 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`: Add the following to your `rules.mk`:
@ -19,7 +19,7 @@ Add the following to your `rules.mk`:
HD44780_ENABLE = yes HD44780_ENABLE = yes
``` ```
## Basic Configuration ## Basic Configuration :id=basic-configuration
Add the following to your `config.h`: 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_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 | |`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`: 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. 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. Initialize the display.
This function should be called only once, before any of the other functions can be called. 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` - `bool cursor`
Whether to show the 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. 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. 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. Turn the display on, and/or set the cursor properties.
This function is called on init. This function is called on init.
#### Arguments #### Arguments :id=api-hd44780-on-arguments
- `bool cursor` - `bool cursor`
Whether to show the 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. 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. Move the cursor to the specified position on the display.
#### Arguments #### Arguments :id=api-hd44780-set-cursor-arguments
- `uint8_t col` - `uint8_t col`
The column number to move to, from 0 to 15 on 16x2 displays. 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. 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. 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` - `char c`
The character to print. 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. Print a string of characters to the display.
#### Arguments #### Arguments :id=api-hd44780-puts-arguments
- `const char *s` - `const char *s`
The string to print. 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. Print a string of characters from PROGMEM to the display.
On ARM devices, this function is simply an alias of `hd44780_puts()`. On ARM devices, this function is simply an alias of `hd44780_puts()`.
#### Arguments #### Arguments :id=api-hd44780-puts-p-arguments
- `const char *s` - `const char *s`
The PROGMEM string to print (ie. `PSTR("Hello")`). 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. Define a custom character.
#### Arguments #### Arguments :id=api-hd44780-define-char-arguments
- `uint8_t index` - `uint8_t index`
The index of the custom character to define, from 0 to 7. 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. Define a custom character from PROGMEM.
On ARM devices, this function is simply an alias of `hd44780_define_char()`. 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` - `uint8_t index`
The index of the custom character to define, from 0 to 7. 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. 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. `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. Write a byte to the display.
#### Arguments #### Arguments :id=api-hd44780-write-arguments
- `uint8_t data` - `uint8_t data`
The byte to send to the display. 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. Read a byte from the display.
#### Arguments #### Arguments :id=api-hd44780-read-arguments
- `bool isData` - `bool isData`
Whether to read the current cursor position, or the character at the cursor. 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. 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. 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. 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` - `uint8_t command`
The command to send. 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. Send a byte of data to the display.
This function waits for the display to clear the busy flag before sending the data. 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` - `uint8_t data`
The byte of data to send. 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. Set the CGRAM address.
This function is used when defining custom characters. This function is used when defining custom characters.
#### Arguments #### Arguments :id=api-hd44780-set-cgram-address-arguments
- `uint8_t address` - `uint8_t address`
The CGRAM address to move to, from `0x00` to `0x3F`. 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. Set the DDRAM address.
This function is used when printing characters to the display, and setting the cursor. 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` - `uint8_t address`
The DDRAM address to move to, from `0x00` to `0x7F`. The DDRAM address to move to, from `0x00` to `0x7F`.

View File

@ -50,10 +50,6 @@ Axes can be configured using one of the following macros:
* `JOYSTICK_AXIS_IN(input_pin, low, rest, high)` * `JOYSTICK_AXIS_IN(input_pin, low, rest, high)`
The ADC samples the provided pin. `low`, `high` and `rest` correspond to the minimum, maximum, and resting (or centered) analog values of the axis, respectively. The ADC samples the provided pin. `low`, `high` and `rest` correspond to the minimum, maximum, and resting (or centered) analog values of the axis, respectively.
* `JOYSTICK_AXIS_IN_OUT(input_pin, output_pin, low, rest, high)`
Same as `JOYSTICK_AXIS_IN()`, but the provided `output_pin` will be pulled high before `input_pin` is read.
* `JOYSTICK_AXIS_IN_OUT_GROUND(input_pin, output_pin, ground_pin, low, rest, high)`
Same as `JOYSTICK_AXIS_IN_OUT()`, but the provided `ground_pin` will be pulled low before reading from `input_pin`.
* `JOYSTICK_AXIS_VIRTUAL` * `JOYSTICK_AXIS_VIRTUAL`
No ADC reading is performed. The value should be provided by user code. No ADC reading is performed. The value should be provided by user code.
@ -160,12 +156,8 @@ Describes a single axis.
#### Members :id=api-joystick-config-t-members #### Members :id=api-joystick-config-t-members
- `pin_t output_pin`
A pin to set as output high when reading the analog value, or `JS_VIRTUAL_AXIS`.
- `pin_t input_pin` - `pin_t input_pin`
The pin to read the analog value from, or `JS_VIRTUAL_AXIS`. The pin to read the analog value from, or `JS_VIRTUAL_AXIS`.
- `pin_t ground_pin`
A pin to set as output low when reading the analog value, or `JS_VIRTUAL_AXIS`.
- `uint16_t min_digit` - `uint16_t min_digit`
The minimum analog value. The minimum analog value.
- `uint16_t mid_digit` - `uint16_t mid_digit`

View File

@ -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: 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)` #### `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)` #### `ko_make_with_layers(modifiers, key, replacement, layers)`
Additionally takes a bitmask `layers` that defines on which layers the override is used. 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 ## 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 { <mod_mask_1>, <mod_mask_2>, ... }
```
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(<kc>)` or `MOD_MASK_xxx` instead.

View File

@ -64,7 +64,7 @@ There are a number of functions (and variables) related to how you can use or ma
| `layer_move(layer)` | Turns specified layer on, and all other layers off. | | `layer_move(layer)` | Turns specified layer on, and all other layers off. |
| `layer_on(layer)` | Turns specified layer on, leaves all other layers in existing state. | | `layer_on(layer)` | Turns specified layer on, leaves all other layers in existing state. |
| `layer_off(layer)` | Turns specified layer off, leaves all other layers in existing state. | | `layer_off(layer)` | Turns specified layer off, leaves all other layers in existing state. |
| `layer_invert(layer)` | Interverts/toggles the state of the specified layer | | `layer_invert(layer)` | Inverts/toggles the state of the specified layer |
| `layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing layer state. | | `layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing layer state. |
| `layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing layer state. | | `layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing layer state. |
| `layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing layer state. | | `layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing layer state. |
@ -155,7 +155,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint8_t current_layer = get_highest_layer(layer_state); uint8_t current_layer = get_highest_layer(layer_state);
// Check if we are within the range, if not quit // Check if we are within the range, if not quit
if (curent_layer > LAYER_CYCLE_END || current_layer < LAYER_CYCLE_START) { if (current_layer > LAYER_CYCLE_END || current_layer < LAYER_CYCLE_START) {
return false; return false;
} }

View File

@ -56,16 +56,16 @@ This is a template indicator function that can be implemented on keyboard level
bool led_update_kb(led_t led_state) { bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state); bool res = led_update_user(led_state);
if(res) { if(res) {
// writePin sets the pin high for 1 and low for 0. // gpio_write_pin sets the pin high for 1 and low for 0.
// In this example the pins are inverted, setting // In this example the pins are inverted, setting
// it low/0 turns it on, and high/1 turns the LED off. // it low/0 turns it on, and high/1 turns the LED off.
// This behavior depends on whether the LED is between the pin // This behavior depends on whether the LED is between the pin
// and VCC or the pin and GND. // and VCC or the pin and GND.
writePin(B0, !led_state.num_lock); gpio_write_pin(B0, !led_state.num_lock);
writePin(B1, !led_state.caps_lock); gpio_write_pin(B1, !led_state.caps_lock);
writePin(B2, !led_state.scroll_lock); gpio_write_pin(B2, !led_state.scroll_lock);
writePin(B3, !led_state.compose); gpio_write_pin(B3, !led_state.compose);
writePin(B4, !led_state.kana); gpio_write_pin(B4, !led_state.kana);
} }
return res; return res;
} }

View File

@ -12,21 +12,20 @@ There is basic support for addressable LED matrix lighting with the I2C IS31FL37
```make ```make
LED_MATRIX_ENABLE = yes 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_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`: You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 | | `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `LED_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 | | | `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 | | | `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first LED driver | |
| `LED_DRIVER_ADDR_2` | (Optional) Address for the second LED driver | | | `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second LED driver | |
| `LED_DRIVER_ADDR_3` | (Optional) Address for the third LED driver | | | `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third LED driver | |
| `LED_DRIVER_ADDR_4` | (Optional) Address for the fourth LED driver | | | `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth LED driver | |
Here is an example using 2 drivers. 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 // 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) // set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring: // The address will vary depending on your wiring:
// 0b1110100 AD <-> GND // 00 AD <-> GND
// 0b1110111 AD <-> VCC // 01 AD <-> SCL
// 0b1110101 AD <-> SCL // 10 AD <-> SDA
// 0b1110110 AD <-> SDA // 11 AD <-> VCC
#define LED_DRIVER_ADDR_1 0b1110100 // ADDR represents A1:A0 of the 7-bit address.
#define LED_DRIVER_ADDR_2 0b1110110 // 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_COUNT 2
#define LED_DRIVER_1_LED_TOTAL 25 #define LED_DRIVER_1_LED_TOTAL 25
#define LED_DRIVER_2_LED_TOTAL 24 #define LED_DRIVER_2_LED_TOTAL 24
#define LED_MATRIX_LED_COUNT (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL) #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`. !> 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 `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = { const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | LED address * | LED address
@ -65,7 +65,7 @@ const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
} }
``` ```
Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-simple.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ). Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-mono.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ).
--- ---
### IS31FLCOMMON :id=is31flcommon ### IS31FLCOMMON :id=is31flcommon
@ -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_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `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 | | | `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_1` | (Optional) Address for the first LED driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional LED drivers | | | `DRIVER_ADDR_<N>` | (Required) Address for the additional LED drivers | |
@ -127,7 +126,6 @@ Here is an example using 2 drivers.
```c ```c
#define DRIVER_ADDR_2 0b0100001 #define DRIVER_ADDR_2 0b0100001
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66 #define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42 #define DRIVER_2_LED_TOTAL 42
#define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -139,13 +137,13 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```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 /* Refer to IS31 manual for these locations
* driver * driver
* | LED address * | LED address
* | | */ * | | */
{ 0, CS1_SW1 }, { 0, SW1_CS1 },
{ 0, CS2_SW1 }, { 0, SW1_CS2 },
// ... // ...
} }
``` ```
@ -158,8 +156,8 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`: Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c ```c
const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = { const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
* LED Index /* LED Index
* | Scaling * | Scaling
* | | */ * | | */
{5, 120}, {5, 120},
@ -247,19 +245,17 @@ enum led_matrix_effects {
LED_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom LED_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom
LED_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in LED_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in
LED_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard 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_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_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_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_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_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_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_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_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 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_LEFT_RIGHT // Sine wave scrolling from left to right LED_MATRIX_WAVE_UP_DOWN, // Sine wave scrolling from up to down
LED_MATRIX_WAVE_UP_DOWN // Sine wave scrolling from up to down
LED_MATRIX_EFFECT_MAX 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_LEFT_RIGHT` |Enables `LED_MATRIX_WAVE_LEFT_RIGHT` |
|`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` | |`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` |
?> These modes don't require any additional defines.
|Reactive Defines |Description | |Reactive Defines |Description |
|-------------------------------------------------------|----------------------------------------------| |-------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` | |`#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_SPLASH` |Enables `LED_MATRIX_SOLID_SPLASH` |
|`#define ENABLE_LED_MATRIX_SOLID_MULTISPLASH` |Enables `LED_MATRIX_SOLID_MULTISPLASH` | |`#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 ## Custom LED Matrix Effects :id=custom-led-matrix-effects
@ -361,19 +355,19 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
## Additional `config.h` Options :id=additional-configh-options ## Additional `config.h` Options :id=additional-configh-options
```c ```c
#define LED_MATRIX_KEYPRESSES // reacts to keypresses #define LED_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define LED_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
#define LED_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
#define LED_MATRIX_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off #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_SLEEP // 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_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_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_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_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_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_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define LED_MATRIX_DEFAULT_FLAGS LED_FLAG_ALL // Sets the default LED flags, 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. #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 ## EEPROM storage :id=eeprom-storage
@ -433,7 +427,7 @@ The EEPROM for it is currently shared with the RGB Matrix system (it's generally
### Indicators :id=indicators ### Indicators :id=indicators
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `led_matrix_indicators_kb` or `led_matrix_indicators_user` function for that: If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, then you can use the `led_matrix_indicators_kb` function on the keyboard level source file, or `led_matrix_indicators_user` function in the user `keymap.c`.
```c ```c
bool led_matrix_indicators_kb(void) { bool led_matrix_indicators_kb(void) {
if (!led_matrix_indicators_user()) { if (!led_matrix_indicators_user()) {

View File

@ -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":"tap", "keycodes": ["F1"]},
{"action":"delay", "duration": "1000"}, {"action":"delay", "duration": 1000},
{"action":"tap", "keycodes": ["PGDN"]} {"action":"tap", "keycodes": ["PGDN"]}
] ]
], ],
@ -69,9 +69,9 @@ The current list of available languages is:
| **italian_osx_iso** | **jis** | **latvian** | **lithuanian_azerty** | | **italian_osx_iso** | **jis** | **latvian** | **lithuanian_azerty** |
| **lithuanian_qwerty** | **norman** | **norwegian** | **portuguese** | | **lithuanian_qwerty** | **norman** | **norwegian** | **portuguese** |
| **portuguese_osx_iso** | **romanian** | **serbian_latin** | **slovak** | | **portuguese_osx_iso** | **romanian** | **serbian_latin** | **slovak** |
| **slovenian** | **spanish_dvorak** | **spanish** | **swedish** | | **slovenian** | **spanish_dvorak** | **spanish_latin_america** | **spanish** |
| **turkish_f** | **turkish_q** | **uk** | **us_international** | | **swedish** | **turkish_f** | **turkish_q** | **uk** |
| **workman** | **workman_zxcvm** | | **us_international** | **workman** | **workman_zxcvm** |
### Macro Basics ### Macro Basics

View File

@ -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_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_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements | |`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_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached | |`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: 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. * 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 ### Constant mode

View File

@ -10,6 +10,7 @@ Tested combinations:
|SSD1306 |128x32 |AVR |Primary support | |SSD1306 |128x32 |AVR |Primary support |
|SSD1306 |128x64 |AVR |Verified working | |SSD1306 |128x64 |AVR |Verified working |
|SSD1306 |128x32 |Arm | | |SSD1306 |128x32 |Arm | |
|SSD1306 |128x64 |Arm |Verified working |
|SH1106 |128x64 |AVR |No scrolling | |SH1106 |128x64 |AVR |No scrolling |
|SH1107 |64x128 |AVR |No scrolling | |SH1107 |64x128 |AVR |No scrolling |
|SH1107 |64x128 |Arm |No scrolling | |SH1107 |64x128 |Arm |No scrolling |
@ -29,17 +30,17 @@ OLED_ENABLE = yes
|OLED Driver |Supported Device | |OLED Driver |Supported Device |
|-------------------|------------------------------------| |-------------------|------------------------------------|
|SSD1306 (default) |For both SSD1306, SH1106, and SH1107| |`ssd1306` (default)|For both SSD1306, SH1106, and SH1107|
e.g. e.g.
```make ```make
OLED_DRIVER = SSD1306 OLED_DRIVER = ssd1306
``` ```
|OLED Transport | | |OLED Transport | |
|---------------|------------------------------------------------| |---------------|------------------------------------------------|
|i2c (default) | Uses I2C 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 | |`spi` | Uses SPI for communication with the OLED panel |
e.g. e.g.
```make ```make
@ -166,6 +167,28 @@ bool oled_task_user(void) {
#endif #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 ## Basic Configuration
These configuration options should be placed in `config.h`. Example: 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_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_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_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 ### I2C Configuration
|Define |Default |Description | |Define |Default |Description |
@ -275,7 +298,7 @@ Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, beca
## OLED API ## OLED API
```c ```c
// OLED rotation enum values are flags // OLED Rotation enum values are flags
typedef enum { typedef enum {
OLED_ROTATION_0 = 0, OLED_ROTATION_0 = 0,
OLED_ROTATION_90 = 1, OLED_ROTATION_90 = 1,
@ -283,7 +306,7 @@ typedef enum {
OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180 OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180
} oled_rotation_t; } 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 // Returns true if the OLED was initialized successfully
bool oled_init(oled_rotation_t rotation); 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 // Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void oled_clear(void); void oled_clear(void);
// Renders the dirty chunks of the buffer to OLED display // Alias to oled_render_dirty to avoid a change in api.
void oled_render(void); #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 // 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 // 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 // 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 // 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); void oled_pan(bool left);
// Returns a pointer to the requested start index in the buffer plus remaining // 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 // 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); 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 // Writes a PROGMEM string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true // Advances the cursor while writing, inverts the pixels if true
// Remapped to call 'void oled_write(const char *data, bool invert);' on ARM // 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 // Writes a PROGMEM string to the buffer at current cursor position
void oled_write_raw_P(const char *data, uint16_t size); 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 // Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on // 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. // Sets scroll speed, 0-7, fastest to slowest. Default is three.
// Does not take effect until scrolling is either started or restarted // Does not take effect until scrolling is either started or restarted
// the ssd1306 supports 8 speeds with the delay // 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 // 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
void oled_scroll_set_speed(uint8_t speed); void oled_scroll_set_speed(uint8_t speed);

View File

@ -14,7 +14,7 @@ In your `rules.mk` add:
OS_DETECTION_ENABLE = yes OS_DETECTION_ENABLE = yes
``` ```
Include `"os_detection.h"` in your `keymap.c`. It will automatically include the required headers file.
It declares `os_variant_t detected_host_os(void);` which you can call to get detected OS. It declares `os_variant_t detected_host_os(void);` which you can call to get detected OS.
It returns one of the following values: It returns one of the following values:
@ -32,14 +32,67 @@ enum {
?> Note that it takes some time after firmware is booted to detect the OS. ?> Note that it takes some time after firmware is booted to detect the OS.
This time is quite short, probably hundreds of milliseconds, but this data may be not ready in keyboard and layout setup functions which run very early during firmware startup. This time is quite short, probably hundreds of milliseconds, but this data may be not ready in keyboard and layout setup functions which run very early during firmware startup.
## Callbacks :id=callbacks
If you want to perform custom actions when the OS is detected, then you can use the `process_detected_host_os_kb` function on the keyboard level source file, or `process_detected_host_os_user` function in the user `keymap.c`.
```c
bool process_detected_host_os_kb(os_variant_t detected_os) {
if (!process_detected_host_os_user(detected_os)) {
return false;
}
switch (detected_os) {
case OS_MACOS:
case OS_IOS:
rgb_matrix_set_color_all(RGB_WHITE);
break;
case OS_WINDOWS:
rgb_matrix_set_color_all(RGB_BLUE);
break;
case OS_LINUX:
rgb_matrix_set_color_all(RGB_ORANGE);
break;
case OS_UNSURE:
rgb_matrix_set_color_all(RGB_RED);
break;
}
return true;
}
```
## OS detection stability
The OS detection is currently handled while the USB device descriptor is being assembled.
The process is done in steps, generating a number of intermediate results until it stabilizes.
We therefore resort to debouncing the result until it has been stable for a given amount of milliseconds.
This amount can be configured, in case your board is not stable within the default debouncing time of 200ms.
## KVM and USB switches
Some KVM and USB switches may not trigger the USB controller on the keyboard to fully reset upon switching machines.
If your keyboard does not redetect the OS in this situation, you can force the keyboard to reset when the USB initialization event is detected, forcing the USB controller to be reconfigured.
## Configuration Options
* `#define OS_DETECTION_DEBOUNCE 200`
* defined the debounce time for OS detection, in milliseconds
* `#define OS_DETECTION_KEYBOARD_RESET`
* enables the keyboard reset upon a USB device reinitilization, such as switching devices on some KVMs
## Debug ## Debug
If OS is guessed incorrectly, you may want to collect data about USB setup packets to refine the detection logic. 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 ```make
OS_DETECTION_DEBUG_ENABLE = yes
CONSOLE_ENABLE = yes CONSOLE_ENABLE = yes
``` ```

View File

@ -69,10 +69,94 @@ The Analog Joystick is an analog (ADC) driven sensor. There are a variety of jo
| `ANALOG_JOYSTICK_Y_AXIS_PIN` | (Required) The pin used for the horizontal/Y axis. | _not defined_ | | `ANALOG_JOYSTICK_Y_AXIS_PIN` | (Required) The pin used for the horizontal/Y axis. | _not defined_ |
| `ANALOG_JOYSTICK_AXIS_MIN` | (Optional) Sets the lower range to be considered movement. | `0` | | `ANALOG_JOYSTICK_AXIS_MIN` | (Optional) Sets the lower range to be considered movement. | `0` |
| `ANALOG_JOYSTICK_AXIS_MAX` | (Optional) Sets the upper range to be considered movement. | `1023` | | `ANALOG_JOYSTICK_AXIS_MAX` | (Optional) Sets the upper range to be considered movement. | `1023` |
| `ANALOG_JOYSTICK_AUTO_AXIS` | (Optional) Sets ranges to be considered movement automatically. | _not defined_ |
| `ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20` | | `ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20` |
| `ANALOG_JOYSTICK_READ_INTERVAL` | (Optional) The interval in milliseconds between reads. | `10` | | `ANALOG_JOYSTICK_READ_INTERVAL` | (Optional) The interval in milliseconds between reads. | `10` |
| `ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` | | `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_ | | `ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
| `ANALOG_JOYSTICK_WEIGHTS` | (Optional) Use custom weights for lever positions. | _not defined_ |
| `ANALOG_JOYSTICK_CUTOFF` | (Optional) Cut off movement when joystick returns to start position. | _not defined_ |
If `ANALOG_JOYSTICK_AUTO_AXIS` is used, then `ANALOG_JOYSTICK_AXIS_MIN` and `ANALOG_JOYSTICK_AXIS_MAX` are ignored.
By default analog joystick implementation uses `x^2` weighting for lever positions. `ANALOG_JOYSTICK_WEIGHTS` allows to experiment with different configurations that might feel better.
E.g. This is weights for `((x-0.4)^3+0.064)/0.282`:
```c
#define ANALOG_JOYSTICK_WEIGHTS {0,2,4,5,7,8,9,10,12,13,14,15,15,16,17,18,18,19,19,20,20,21,21,21,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,25,25,25,26,26,26,27,28,28,29,29,30,31,32,33,34,35,36,37,38,40,41,43,44,46,48,49,51,53,56,58,60,62,65,68,70,73,76,79,82,85,89,92,96,100}
```
You can use following JS code to generate weights for different formulas:
```js
JSON.stringify(Array.from(Array(101).keys()).map(x => Math.ceil((((x/100-0.4)**3+0.064)/0.282*100))))
```
### 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 ### Cirque Trackpad
@ -93,12 +177,13 @@ This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the
#### Common settings #### Common settings
| Setting | Description | Default | | Setting | Description | Default |
| -------------------------------- | ---------------------------------------------------------- | ------------------------------------------- | | ------------------------------------ | ---------------------------------------------------------- | ------------------------------------------- |
| `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` | | `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` |
| `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` | | `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` |
| `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ | | `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ |
| `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ | | `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ |
| `CIRQUE_PINNACLE_SKIP_SENSOR_CHECK` | (Optional) Skips sensor presence check | _not defined_ |
**`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be. **`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.
@ -132,12 +217,13 @@ Also see the `POINTING_DEVICE_TASK_THROTTLE_MS`, which defaults to 10ms when usi
#### Absolute mode settings #### Absolute mode settings
| Setting | Description | Default | | Setting | Description | Default |
| -------------------------------- | ---------------------------------------------------------- | ------------------ | |-----------------------------------------|-------------------------------------------------------------------------|-------------|
| `CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` | | `CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` |
| `CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` | | `CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` |
| `CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` | | `CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` |
| `CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` | | `CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` |
| `CIRQUE_PINNACLE_REACHABLE_CALIBRATION` | (Optional) Enable console messages to aide in calibrating above values. | not defined |
#### Absolute mode gestures #### Absolute mode gestures
@ -643,6 +729,7 @@ There are a few ways to control the auto mouse feature with both `config.h` opti
| `AUTO_MOUSE_TIME` | (Optional) Time layer remains active after activation | _ideally_ (250-1000) | _ms_ | `650 ms` | | `AUTO_MOUSE_TIME` | (Optional) Time layer remains active after activation | _ideally_ (250-1000) | _ms_ | `650 ms` |
| `AUTO_MOUSE_DELAY` | (Optional) Lockout time after non-mouse key is pressed | _ideally_ (100-1000) | _ms_ | `TAPPING_TERM` or `200 ms` | | `AUTO_MOUSE_DELAY` | (Optional) Lockout time after non-mouse key is pressed | _ideally_ (100-1000) | _ms_ | `TAPPING_TERM` or `200 ms` |
| `AUTO_MOUSE_DEBOUNCE` | (Optional) Time delay from last activation to next update | _ideally_ (10 - 100) | _ms_ | `25 ms` | | `AUTO_MOUSE_DEBOUNCE` | (Optional) Time delay from last activation to next update | _ideally_ (10 - 100) | _ms_ | `25 ms` |
| `AUTO_MOUSE_THRESHOLD` | (Optional) Amount of mouse movement required to switch layers | 0 - | _units_ | `10 units` |
### Adding mouse keys ### Adding mouse keys
@ -735,9 +822,11 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#### Set different target layer when a particular layer is active: #### 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. 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* *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 ```c
// in keymap.c // in keymap.c

View File

@ -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. 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. ?> 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.

View File

@ -155,6 +155,29 @@ In your keyboard config.h:
#endif #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 ## Additional Settings :id=additional-settings
### PS/2 Mouse Features :id=ps2-mouse-features ### PS/2 Mouse Features :id=ps2-mouse-features

View File

@ -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. Add the following to your `rules.mk`:
In your `rules.mk` add:
```make ```make
RAW_ENABLE = yes 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 ```c
void raw_hid_receive(uint8_t *data, uint8_t length) { 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 ```c
void raw_hid_receive(uint8_t *data, uint8_t length) { 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.
Make sure to flash raw enabled firmware before proceeding with working on the host side. For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed.
## Host (Windows/macOS/Linux) ```python
import sys
import hid
This is the more complicated part as it will require some digging. vendor_id = 0x4335
product_id = 0x0002
To connect your host computer to your keyboard with raw HID you need four pieces of information about your keyboard: usage_page = 0xFF60
usage = 0x61
report_length = 32
1. Vendor ID def get_raw_hid_interface():
2. Product ID device_interfaces = hid.enumerate(vendor_id, product_id)
3. Usage Page raw_hid_interfaces = [i for i in device_interfaces if i['usage_page'] == usage_page and i['usage'] == usage]
4. Usage
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`. if len(raw_hid_interfaces) == 0:
return None
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`. interface = hid.Device(path=raw_hid_interfaces[0]['path'])
By default, **Usage Page** is `0xFF60` and **Usage** is `0x61`. print(f"Manufacturer: {interface.manufacturer}")
print(f"Product: {interface.product}")
### Building your host return interface
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: def send_raw_report(data):
interface = get_raw_hid_interface()
* Node: [node-hid](https://github.com/node-hid/node-hid). if interface is None:
* C: [hidapi](https://github.com/libusb/hidapi). print("No device found")
* Java: [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java). sys.exit(1)
* 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. request_data = [0x00] * (report_length + 1) # First byte is Report ID
request_data[1:len(data) + 1] = data
request_report = bytes(request_data)
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. print("Request:")
print(request_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. try:
Unlike Vendor ID and Product ID though, Usage Page and Usage are necessary for successful communication. interface.write(request_report)
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. response_report = interface.read(report_length, timeout=1000)
print("Response:")
print(response_report)
finally:
interface.close()
if __name__ == '__main__':
send_raw_report([
0x41
])
```
## API :id=api
### `void raw_hid_receive(uint8_t *data, uint8_t length)` :id=api-raw-hid-receive
Callback, invoked when a raw HID report has been received from the host.
#### Arguments :id=api-raw-hid-receive-arguments
- `uint8_t *data`
A pointer to the received data. Always 32 bytes in length.
- `uint8_t length`
The length of the buffer. Always 32.
---
### `void raw_hid_send(uint8_t *data, uint8_t length)` :id=api-raw-hid-send
Send an HID report.
#### Arguments :id=api-raw-hid-send-arguments
- `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.

View File

@ -12,22 +12,21 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make ```make
RGB_MATRIX_ENABLE = yes 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_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`: You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 | | `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `IS31FL3731_I2C_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 | | | `IS31FL3731_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 | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | | | `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | | | `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | | | `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | | | `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | | | `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
Here is an example using 2 drivers. 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 // 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) // set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring: // The address will vary depending on your wiring:
// 0b1110100 AD <-> GND // 00 AD <-> GND
// 0b1110111 AD <-> VCC // 01 AD <-> SCL
// 0b1110101 AD <-> SCL // 10 AD <-> SDA
// 0b1110110 AD <-> SDA // 11 AD <-> VCC
#define DRIVER_ADDR_1 0b1110100 // ADDR represents A1:A0 of the 7-bit address.
#define DRIVER_ADDR_2 0b1110110 // 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_COUNT 2
#define DRIVER_1_LED_TOTAL 25 #define DRIVER_1_LED_TOTAL 25
#define DRIVER_2_LED_TOTAL 24 #define DRIVER_2_LED_TOTAL 24
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #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`. !> 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 `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = { const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
@ -76,41 +76,40 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make ```make
RGB_MATRIX_ENABLE = yes 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_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`: You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 | | `IS31FL3733_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `IS31FL3733_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 | | `IS31FL3733_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF | | `IS31FL3733_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) | | `IS31FL3733_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) | | `IS31FL3733_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 | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | | | `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | | | `IS31FL3733_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | | | `IS31FL3733_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | | | `IS31FL3733_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | | | `IS31FL3733_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
| `DRIVER_SYNC_1` | (Optional) Sync configuration for the first RGB driver | 0 | | `IS31FL3733_SYNC_1` | (Optional) Sync configuration for the first RGB driver | 0 |
| `DRIVER_SYNC_2` | (Optional) Sync configuration for the second RGB driver | 0 | | `IS31FL3733_SYNC_2` | (Optional) Sync configuration for the second RGB driver | 0 |
| `DRIVER_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 | | `IS31FL3733_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 |
| `DRIVER_SYNC_4` | (Optional) Sync configuration for the fourth 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 (`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 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:
| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description | | `IS31FL3733_SWPULLUP/IS31FL3733_CSPULLUP` | Description |
|----------------------|-------------| |----------------------|-------------|
| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting | | `IS31FL3733_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) | | `IS31FL3733_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
| `PUR_3KR` | The 3k Ohm resistor used at all times | | `IS31FL3733_PUR_3KR` | The 3k Ohm resistor used at all times |
| `PUR_4KR` | The 4k Ohm resistor used at all times | | `IS31FL3733_PUR_4KR` | The 4k Ohm resistor used at all times |
| `PUR_8KR` | The 8k Ohm resistor used at all times | | `IS31FL3733_PUR_8KR` | The 8k Ohm resistor used at all times |
| `PUR_16KR` | The 16k Ohm resistor used at all times | | `IS31FL3733_PUR_16KR` | The 16k Ohm resistor used at all times |
| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) | | `IS31FL3733_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers. 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 // 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) // set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring: // The address will vary depending on your wiring:
// 00 <-> GND // 00 ADDRn <-> GND
// 01 <-> SCL // 01 ADDRn <-> SCL
// 10 <-> SDA // 10 ADDRn <-> SDA
// 11 <-> VCC // 11 ADDRn <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address. // ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address. // ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b101(ADDR2)(ADDR1) // The result is: 0b101(ADDR2)(ADDR1)
#define DRIVER_ADDR_1 0b1010000 #define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND
#define DRIVER_ADDR_2 0b1010011 #define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_VCC
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 58 #define DRIVER_1_LED_TOTAL 58
#define DRIVER_2_LED_TOTAL 10 #define DRIVER_2_LED_TOTAL 10
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -141,19 +139,19 @@ Currently only 4 drivers are supported, but it would be trivial to support all 8
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = { const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
* | | G location * | | G location
* | | | B location * | | | B location
* | | | | */ * | | | | */
{0, B_1, A_1, C_1}, {0, SW1_CS1, SW1_CS2, SW1_CS3},
.... ....
} }
``` ```
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/led/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now). Where `SWx_CSy` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/led/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
--- ---
### IS31FL3736 :id=is31fl3736 ### IS31FL3736 :id=is31fl3736
@ -162,7 +160,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make ```make
RGB_MATRIX_ENABLE = yes 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_<N>` defines for IC's that are not present on your keyboard. You can use between 1 and 4 IS31FL3736 IC's. Do not specify `DRIVER_ADDR_<N>` 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 | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 | | `IS31FL3736_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `IS31FL3736_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 | | `IS31FL3736_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF | | `IS31FL3736_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) | | `IS31FL3736_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) | | `IS31FL3736_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 | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | | | `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | | | `IS31FL3736_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | | | `IS31FL3736_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | | | `IS31FL3736_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth 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 | | `IS31FL3736_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) | | `IS31FL3736_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) | | `IS31FL3736_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) | | `IS31FL3736_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) | | `IS31FL3736_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) | | `IS31FL3736_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) | | `IS31FL3736_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_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers. 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 // 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) // set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring: // The address will vary depending on your wiring:
// 0000 <-> GND // 00 ADDRn <-> GND
// 0101 <-> SCL // 01 ADDRn <-> SCL
// 1010 <-> SDA // 10 ADDRn <-> SDA
// 1111 <-> VCC // 11 ADDRn <-> VCC
// ADDR represents A3:A0 of the 7-bit address. // ADDR1 represents A1:A0 of the 7-bit address.
// The result is: 0b101(ADDR) // ADDR2 represents A3:A2 of the 7-bit address.
#define DRIVER_ADDR_1 0b1010000 // The result is: 0b101(ADDR2)(ADDR1)
#define DRIVER_ADDR_2 0b1010001 #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_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 32 #define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -221,14 +218,14 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = { const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
* | | G location * | | G location
* | | | B location * | | | B location
* | | | | */ * | | | | */
{0, B_1, A_1, C_1}, {0, SW1_CS1, SW1_CS2, SW1_CS3},
.... ....
} }
``` ```
@ -238,7 +235,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
```make ```make
RGB_MATRIX_ENABLE = yes 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_<N>` defines for IC's that are not present on your keyboard. You can use between 1 and 4 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_<N>` 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 | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 | | `IS31FL3737_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `IS31FL3737_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 | | `IS31FL3737_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF | | `IS31FL3737_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) | | `IS31FL3737_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) | | `IS31FL3737_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 | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | | | `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | | | `IS31FL3737_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | | | `IS31FL3737_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | | | `IS31FL3737_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth 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 | | `IS31FL3737_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) | | `IS31FL3737_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) | | `IS31FL3737_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) | | `IS31FL3737_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) | | `IS31FL3737_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) | | `IS31FL3737_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) | | `IS31FL3737_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_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers. 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 // 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) // set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring: // The address will vary depending on your wiring:
// 0000 <-> GND // 0000 ADDR <-> GND
// 0101 <-> SCL // 0101 ADDR <-> SCL
// 1010 <-> SDA // 1010 ADDR <-> SDA
// 1111 <-> VCC // 1111 ADDR <-> VCC
// ADDR represents A3:A0 of the 7-bit address. // ADDR represents A3:A0 of the 7-bit address.
// The result is: 0b101(ADDR) // The result is: 0b101(ADDR)
#define DRIVER_ADDR_1 0b1010000 #define IS31FL3737_I2C_ADDRESS_1 IS31FL3737_I2C_ADDRESS_GND
#define DRIVER_ADDR_2 0b1010001 #define IS31FL3737_I2C_ADDRESS_2 IS31FL3737_I2C_ADDRESS_SCL
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 30 #define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 36 #define DRIVER_2_LED_TOTAL 36
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -297,19 +292,19 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = { const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
* | | G location * | | G location
* | | | B location * | | | B location
* | | | | */ * | | | | */
{0, B_1, A_1, C_1}, {0, SW1_CS1, SW1_CS2, SW1_CS3},
.... ....
} }
``` ```
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1`, `2`, or `3` for now). Where `SWx_CSy` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1`, `2`, or `3` for now).
--- ---
### IS31FLCOMMON :id=is31flcommon ### IS31FLCOMMON :id=is31flcommon
@ -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_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 | | `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 | | | `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_1` | (Optional) Address for the first RGB driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional RGB drivers | | | `DRIVER_ADDR_<N>` | (Required) Address for the additional RGB drivers | |
@ -373,7 +367,6 @@ Here is an example using 2 drivers.
```c ```c
#define DRIVER_ADDR_2 0b0100001 #define DRIVER_ADDR_2 0b0100001
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66 #define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42 #define DRIVER_2_LED_TOTAL 42
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -386,14 +379,14 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```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 /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
* | | G location * | | G location
* | | | B location * | | | B location
* | | | | */ * | | | | */
{0, CS1_SW1, CS2_SW1, CS3_SW1}, {0, SW1_CS1, SW1_CS2, SW1_CS3},
.... ....
} }
``` ```
@ -406,8 +399,8 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`: Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c ```c
const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = { const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
* LED Index /* LED Index
* | R scaling * | R scaling
* | | G scaling * | | G scaling
* | | | B scaling * | | | B scaling
@ -428,7 +421,7 @@ There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{
```make ```make
RGB_MATRIX_ENABLE = yes RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = WS2812 RGB_MATRIX_DRIVER = ws2812
``` ```
Configure the hardware via your `config.h`: 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 ```make
RGB_MATRIX_ENABLE = yes RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = APA102 RGB_MATRIX_DRIVER = apa102
``` ```
Configure the hardware via your `config.h`: Configure the hardware via your `config.h`:
@ -465,41 +458,39 @@ Configure the hardware via your `config.h`:
``` ```
--- ---
### AW20216 :id=aw20216 ### AW20216S :id=aw20216s
There is basic support for addressable RGB matrix lighting with the SPI AW20216 RGB controller. To enable it, add this to your `rules.mk`: 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 ```make
RGB_MATRIX_ENABLE = yes 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_<N>_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_<N>_xxx` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `DRIVER_1_CS` | (Required) MCU pin connected to first RGB driver chip select line | B13 | | `AW20216S_CS_PIN_1` | (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 | | | `AW20216S_CS_PIN_2` | (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 | | `AW20216S_EN_PIN_1` | (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_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_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_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 | | | `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 | | `AW20216S_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 | | `AW20216S_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 | | `AW20216S_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_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. Here is an example using 2 drivers.
```c ```c
#define DRIVER_1_CS B13 #define AW20216S_CS_PIN_1 B13
#define DRIVER_2_CS B14 #define AW20216S_CS_PIN_2 B14
// Hardware enable lines may be connected to the same pin // Hardware enable lines may be connected to the same pin
#define DRIVER_1_EN C13 #define AW20216S_EN_PIN_1 C13
#define DRIVER_2_EN C13 #define AW20216S_EN_PIN_2 C13
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66 #define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 32 #define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) #define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
@ -510,26 +501,26 @@ Here is an example using 2 drivers.
Define these arrays listing all the LEDs in your `<keyboard>.c`: Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c ```c
const aw_led PROGMEM g_aw_leds[RGB_MATRIX_LED_COUNT] = { const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
/* Each AW20216 channel is controlled by a register at some offset between 0x00 /* Each AW20216S channel is controlled by a register at some offset between 0x00
* and 0xD7 inclusive. * 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 pin locations.
* driver * driver
* | R location * | R location
* | | G location * | | G location
* | | | B location * | | | B location
* | | | | */ * | | | | */
{ 0, CS1_SW1, CS2_SW1, CS3_SW1 }, { 0, SW1_CS1, SW1_CS2, SW1_CS3 },
{ 0, CS4_SW1, CS5_SW1, CS6_SW1 }, { 0, SW1_CS4, SW1_CS5, SW1_CS6 },
{ 0, CS7_SW1, CS8_SW1, CS9_SW1 }, { 0, SW1_CS7, SW1_CS8, SW1_CS9 },
{ 0, CS10_SW1, CS11_SW1, CS12_SW1 }, { 0, SW1_CS10, SW1_CS11, SW1_CS12 },
{ 0, CS13_SW1, CS14_SW1, CS15_SW1 }, { 0, SW1_CS13, SW1_CS14, SW1_CS15 },
... ...
{ 1, CS1_SW1, CS2_SW1, CS3_SW1 }, { 1, SW1_CS1, SW1_CS2, SW1_CS3 },
{ 1, CS13_SW1, CS14_SW1, CS15_SW1 }, { 1, SW1_CS13, SW1_CS14, SW1_CS15 },
{ 1, CS16_SW1, CS17_SW1, CS18_SW1 }, { 1, SW1_CS16, SW1_CS17, SW1_CS18 },
{ 1, CS4_SW2, CS5_SW2, CS6_SW2 }, { 1, SW2_CS4, SW2_CS5, SW2_CS6 },
... ...
}; };
``` ```
@ -642,6 +633,7 @@ enum rgb_matrix_effects {
RGB_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard 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_BEACON, // Full tighter gradient spinning around center of keyboard
RGB_MATRIX_RAINBOW_PINWHEELS, // Full dual gradients spinning two halfs 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_RAINDROPS, // Randomly changes a single key's hue
RGB_MATRIX_JELLYBEAN_RAINDROPS, // Randomly changes a single key's hue and saturation 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 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_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_FLOW, // Pulsing RGB flow along LED wiring with random hues
RGB_MATRIX_PIXEL_RAIN, // Randomly light keys 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_TYPING_HEATMAP, // How hot is your WPM!
RGB_MATRIX_DIGITAL_RAIN, // That famous computer simulation 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_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, // 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_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_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_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_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_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_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_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_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_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 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 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_DUAL_BEACON` |Enables `RGB_MATRIX_DUAL_BEACON` |
|`#define ENABLE_RGB_MATRIX_RAINBOW_BEACON` |Enables `RGB_MATRIX_RAINBOW_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_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_RAINDROPS` |Enables `RGB_MATRIX_RAINDROPS` |
|`#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS` |Enables `RGB_MATRIX_JELLYBEAN_RAINDROPS` | |`#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS` |Enables `RGB_MATRIX_JELLYBEAN_RAINDROPS` |
|`#define ENABLE_RGB_MATRIX_HUE_BREATHING` |Enables `RGB_MATRIX_HUE_BREATHING` | |`#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_FRACTAL` |Enables `RGB_MATRIX_PIXEL_FRACTAL` |
|`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` | |`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` |
|`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` | |`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` |
|`#define ENABLE_RGB_MATRIX_STARLIGHT` |Enables `RGB_MATRIX_STARLIGHT` |
?> These modes don't require any additional defines. |`#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 | |Framebuffer Defines |Description |
|------------------------------------------------------|----------------------------------------------| |------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_RGB_MATRIX_TYPING_HEATMAP` |Enables `RGB_MATRIX_TYPING_HEATMAP` | |`#define ENABLE_RGB_MATRIX_TYPING_HEATMAP` |Enables `RGB_MATRIX_TYPING_HEATMAP` |
|`#define ENABLE_RGB_MATRIX_DIGITAL_RAIN` |Enables `RGB_MATRIX_DIGITAL_RAIN` | |`#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 | |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_SPLASH` |Enables `RGB_MATRIX_SOLID_SPLASH` |
|`#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Enables `RGB_MATRIX_SOLID_MULTISPLASH` | |`#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 ### RGB Matrix Effect Typing Heatmap :id=rgb-matrix-effect-typing-heatmap
@ -872,22 +867,22 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
## Additional `config.h` Options :id=additional-configh-options ## Additional `config.h` Options :id=additional-configh-options
```c ```c
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses #define RGB_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
#define RGB_MATRIX_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off #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_SLEEP // 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) #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)
#define RGB_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 RGB_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 RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
#define RGB_MATRIX_DEFAULT_ON true // Sets the default enabled state, if none has been set
#define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT // Sets the default mode, if none has been set #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_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_SAT 255 // Sets the default saturation value, 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_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_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define RGB_MATRIX_DEFAULT_FLAGS LED_FLAG_ALL // Sets the default LED flags, 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_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. #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 #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
``` ```
@ -964,7 +959,7 @@ The EEPROM for it is currently shared with the LED Matrix system (it's generally
### Indicators :id=indicators ### Indicators :id=indicators
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `rgb_matrix_indicators_kb` or `rgb_matrix_indicators_user` function for that: If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, then you can use the `rgb_matrix_indicators_kb` function on the keyboard level source file, or `rgb_matrix_indicators_user` function in the user `keymap.c`.
```c ```c
bool rgb_matrix_indicators_kb(void) { bool rgb_matrix_indicators_kb(void) {
if (!rgb_matrix_indicators_user()) { if (!rgb_matrix_indicators_user()) {

View File

@ -28,18 +28,18 @@ For APA102 LEDs, add the following to your `rules.mk`:
```make ```make
RGBLIGHT_ENABLE = yes 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. 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.
|Define |Description | |Define |Description |
|---------------|-------------------------------------------------------------------------| |--------------------|-------------------------------------------------------------------------|
|`WS2812_DI_PIN`|The pin connected to the data pin of the LEDs (WS2812) | |`WS2812_DI_PIN` |The pin connected to the data pin of the LEDs (WS2812) |
|`APA102_DI_PIN`|The pin connected to the data pin of the LEDs (APA102) | |`APA102_DI_PIN` |The pin connected to the data pin of the LEDs (APA102) |
|`APA102_CI_PIN`|The pin connected to the clock pin of the LEDs (APA102) | |`APA102_CI_PIN` |The pin connected to the clock pin of the LEDs (APA102) |
|`RGBLED_NUM` |The number of LEDs connected | |`RGBLIGHT_LED_COUNT`|The number of LEDs connected |
|`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half| |`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half|
Then you should be able to use the keycodes below to change the RGB lighting to your liking. Then you should be able to use the keycodes below to change the RGB lighting to your liking.
@ -90,7 +90,7 @@ Your RGB lighting can be configured by placing these `#define`s in your `config.
|Define |Default |Description | |Define |Default |Description |
|---------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------| |---------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------|
|`RGBLIGHT_HUE_STEP` |`10` |The number of steps to cycle through the hue by | |`RGBLIGHT_HUE_STEP` |`8` |The number of steps to cycle through the hue by |
|`RGBLIGHT_SAT_STEP` |`17` |The number of steps to increment the saturation by | |`RGBLIGHT_SAT_STEP` |`17` |The number of steps to increment the saturation by |
|`RGBLIGHT_VAL_STEP` |`17` |The number of steps to increment the brightness by | |`RGBLIGHT_VAL_STEP` |`17` |The number of steps to increment the brightness by |
|`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level | |`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level |
@ -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_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_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_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 ## Effects and Animations
@ -151,28 +152,28 @@ Use these defines to add or remove animations from the firmware. When you are ru
The following options are used to tweak the various animations: The following options are used to tweak the various animations:
|Define |Default |Description | |Define |Default |Description |
|------------------------------------|-------------|-----------------------------------------------------------------------------------------------| |------------------------------------|--------------------|-----------------------------------------------------------------------------------------------|
|`RGBLIGHT_EFFECT_BREATHE_CENTER` |*Not defined*|If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 | |`RGBLIGHT_EFFECT_BREATHE_CENTER` |*Not defined* |If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 |
|`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 | |`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 |
|`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`40` |How long (in milliseconds) to wait between animation steps for the "Christmas" animation | |`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`40` |How long (in milliseconds) to wait between animation steps for the "Christmas" animation |
|`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation | |`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation |
|`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLED_NUM` |The number of LEDs to have the "Knight" animation travel | |`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLIGHT_LED_COUNT`|The number of LEDs to have the "Knight" animation travel |
|`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation | |`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation |
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by | |`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls | |`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation | |`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`200` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) | |`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`200` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) | |`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
### Example Usage to Reduce Memory Footprint ### Example Usage to Reduce Memory Footprint
1. Use `#undef` to selectively disable animations. The following would disable two animations and save about 4KiB: 1. Use `#undef` to selectively disable animations. The following would disable two animations and save about 4KiB:
```diff ```diff
#undef RGBLED_NUM #undef RGBLIGHT_LED_COUNT
+#undef RGBLIGHT_EFFECT_STATIC_GRADIENT +#undef RGBLIGHT_EFFECT_STATIC_GRADIENT
+#undef RGBLIGHT_EFFECT_RAINBOW_SWIRL +#undef RGBLIGHT_EFFECT_RAINBOW_SWIRL
#define RGBLED_NUM 12 #define RGBLIGHT_LED_COUNT 12
#define RGBLIGHT_HUE_STEP 8 #define RGBLIGHT_HUE_STEP 8
#define RGBLIGHT_SAT_STEP 8 #define RGBLIGHT_SAT_STEP 8
``` ```
@ -370,9 +371,9 @@ If you need to change your RGB lighting in code, for example in a macro to chang
Example: Example:
```c ```c
sethsv(HSV_WHITE, (LED_TYPE *)&led[0]); // led 0 sethsv(HSV_WHITE, (rgb_led_t *)&led[0]); // led 0
sethsv(HSV_RED, (LED_TYPE *)&led[1]); // led 1 sethsv(HSV_RED, (rgb_led_t *)&led[1]); // led 1
sethsv(HSV_GREEN, (LED_TYPE *)&led[2]); // led 2 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. rgblight_set(); // Utility functions do not call rgblight_set() automatically, so they need to be called explicitly.
``` ```
@ -385,10 +386,10 @@ rgblight_set(); // Utility functions do not call rgblight_set() automatically, s
#### direct operation #### direct operation
|Function |Description | |Function |Description |
|--------------------------------------------|-------------| |--------------------------------------------|-------------|
|`rgblight_setrgb_at(r, g, b, index)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) | |`rgblight_setrgb_at(r, g, b, index)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `index` is between 0 and `RGBLIGHT_LED_COUNT` (not written to EEPROM) |
|`rgblight_sethsv_at(h, s, v, index)` |Set a single LED to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) | |`rgblight_sethsv_at(h, s, v, index)` |Set a single LED to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `index` is between 0 and `RGBLIGHT_LED_COUNT` (not written to EEPROM) |
|`rgblight_setrgb_range(r, g, b, start, end)`|Set a continuous range of LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)| |`rgblight_setrgb_range(r, g, b, start, end)`|Set a continuous range of LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `start`(included) and `stop`(excluded) are between 0 and `RGBLIGHT_LED_COUNT` (not written to EEPROM)|
|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)| |`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLIGHT_LED_COUNT` (not written to EEPROM)|
|`rgblight_setrgb(r, g, b)` |Set effect range LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) | |`rgblight_setrgb(r, g, b)` |Set effect range LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) | |`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) | |`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
@ -518,44 +519,12 @@ By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED
```c ```c
// config.h // config.h
#define RGBLED_NUM 4 #define RGBLIGHT_LED_COUNT 4
#define RGBLIGHT_LED_MAP { 3, 2, 1, 0 } #define RGBLIGHT_LED_MAP { 3, 2, 1, 0 }
``` ```
<img src="https://user-images.githubusercontent.com/2170248/55743725-08ad7a80-5a6e-11e9-83ed-126a2b0209fc.JPG" alt="simple mapped" width="50%"/> <img src="https://user-images.githubusercontent.com/2170248/55743725-08ad7a80-5a6e-11e9-83ed-126a2b0209fc.JPG" alt="simple mapped" width="50%"/>
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 ## 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. 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.
@ -572,14 +541,44 @@ In addition to setting the Clipping Range, you can use `RGBLIGHT_LED_MAP` togeth
```c ```c
// config.h // config.h
#define RGBLED_NUM 8 #define RGBLIGHT_LED_COUNT 8
#define RGBLIGHT_LED_MAP { 7, 6, 5, 4, 3, 2, 1, 0 } #define RGBLIGHT_LED_MAP { 7, 6, 5, 4, 3, 2, 1, 0 }
// some soruce // some source
rgblight_set_clipping_range(3, 4); rgblight_set_clipping_range(3, 4);
``` ```
<img src="https://user-images.githubusercontent.com/2170248/55743747-119e4c00-5a6e-11e9-91e5-013203ffae8a.JPG" alt="clip mapped" width="70%"/> <img src="https://user-images.githubusercontent.com/2170248/55743747-119e4c00-5a6e-11e9-91e5-013203ffae8a.JPG" alt="clip mapped" width="70%"/>
## Hardware Modification ## 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. 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.

View File

@ -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. 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. ?> 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`: 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 SEND_STRING_ENABLE = yes
``` ```
## Basic Configuration ## Basic Configuration :id=basic-configuration
Add the following to your `config.h`: 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.| |`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. | |`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_`. 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` | |`\t` |`\x1B`|`TAB`|`KC_TAB` |
| |`\x7F`|`DEL`|`KC_DELETE` | | |`\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). 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. 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. 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")); 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. Type out a string of ASCII characters.
This function simply calls `send_string_with_delay(string, 0)`. This function simply calls `send_string_with_delay(string, 0)`.
#### Arguments #### Arguments :id=api-send-string-arguments
- `const char *string` - `const char *string`
The string to type out. 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. 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` - `const char *string`
The string to type out. 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. Type out a PROGMEM string of ASCII characters.
On ARM devices, this function is simply an alias for `send_string_with_delay(string, 0)`. 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` - `const char *string`
The string to type out. 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. 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)`. 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` - `const char *string`
The string to type out. 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. Type out an ASCII character.
#### Arguments #### Arguments :id=api-send-char-arguments
- `char ascii_code` - `char ascii_code`
The character to type. 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. Type out an eight digit (unsigned 32-bit) hexadecimal value.
The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`. The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`.
#### Arguments #### Arguments :id=api-send-dword-arguments
- `uint32_t number` - `uint32_t number`
The value to type, from 0 to 4,294,967,295. 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. Type out a four digit (unsigned 16-bit) hexadecimal value.
The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`. The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`.
#### Arguments #### Arguments :id=api-send-word-arguments
- `uint16_t number` - `uint16_t number`
The value to type, from 0 to 65,535. 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. Type out a two digit (8-bit) hexadecimal value.
The format is `[0-9a-f]{2}`, eg. `00` through `ff`. The format is `[0-9a-f]{2}`, eg. `00` through `ff`.
#### Arguments #### Arguments :id=api-send-byte-arguments
- `uint8_t number` - `uint8_t number`
The value to type, from 0 to 255. 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. Type out a single hexadecimal digit.
The format is `[0-9a-f]{1}`, eg. `0` through `f`. The format is `[0-9a-f]{1}`, eg. `0` through `f`.
#### Arguments #### Arguments :id=api-send-nibble-arguments
- `uint8_t number` - `uint8_t number`
The value to type, from 0 to 15. 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 `/`. 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)`. 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)`. Shortcut macro for `send_string_with_delay_P(PSTR(string), interval)`.

View File

@ -119,12 +119,12 @@ You can configure the firmware to read key matrix pins on the controller to dete
The first pin is the output pin and the second is the input pin. The first pin is the output pin and the second is the input pin.
Some keyboards have unused intersections in the key matrix. This setting uses one of these unused intersections to determine the handness. Some keyboards have unused intersections in the key matrix. This setting uses one of these unused intersections to determine the handedness.
Normally, when a diode is connected to an intersection, it is judged to be left. If you add the following definition, it will be judged to be right. Normally, when a diode is connected to an intersection, it is judged to be right. If you add the following definition, it will be judged to be left.
```c ```c
#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT #define SPLIT_HAND_MATRIX_GRID_LOW_IS_LEFT
``` ```
Note that adding a diode at a previously unused intersection will effectively tell the firmware that there is a key held down at that point. You can instruct qmk to ignore that intersection by defining `MATRIX_MASKED` and then defining a `matrix_row_t matrix_mask[MATRIX_ROWS]` array in your keyboard config. Each bit of a single value (starting form the least-significant bit) is used to tell qmk whether or not to pay attention to key presses at that intersection. Note that adding a diode at a previously unused intersection will effectively tell the firmware that there is a key held down at that point. You can instruct qmk to ignore that intersection by defining `MATRIX_MASKED` and then defining a `matrix_row_t matrix_mask[MATRIX_ROWS]` array in your keyboard config. Each bit of a single value (starting form the least-significant bit) is used to tell qmk whether or not to pay attention to key presses at that intersection.
@ -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 I<sup>2</sup>C on the board, you will need to set this, and to something other than D0 and D1 (as these are used for I<sup>2</sup>C communication). However, if you are using serial and I<sup>2</sup>C on the board, you will need to set this, and to something other than D0 and D1 (as these are used for I<sup>2</sup>C communication).
```c ```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: 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 #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 ```c
#define SPLIT_ACTIVITY_ENABLE #define SPLIT_ACTIVITY_ENABLE

View File

@ -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). !> 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). 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 ## 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. > 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| |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_RES2`||(Reset 2)|
|`STN_PWR`||(Power)| |`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 | |Combined key | Key1 | Key 2 |
|---------------|--------|----------| |---------------|--------|----------|

View File

@ -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_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(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(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. 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.
@ -173,7 +173,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations
action = &tap_dance_actions[TD_INDEX(keycode)]; action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(keycode)];
if (!record->event.pressed && action->state.count && !action->state.finished) { if (!record->event.pressed && action->state.count && !action->state.finished) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
tap_code16(tap_hold->tap); tap_code16(tap_hold->tap);

View File

@ -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_lower_layer(layer)` | Changes the "lower" layer*. |
| `set_tri_layer_upper_layer(layer)` | Changes the "upper" layer*. | | `set_tri_layer_upper_layer(layer)` | Changes the "upper" layer*. |
| `set_tri_layer_adjust_layer(layer)` | Changes the "adjust" 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_lower_layer()` | Gets the current "lower" layer. |
| `get_tri_layer_upper_layer()` | Gets the current "upper" layer. | | `get_tri_layer_upper_layer()` | Gets the current "upper" layer. |
| `get_tri_layer_adjust_layer()` | Gets the current "adjust" layer. | | `get_tri_layer_adjust_layer()` | Gets the current "adjust" layer. |

View File

@ -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). 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.
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.
## 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
```
<br> ## Basic Configuration :id=basic-configuration
### 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_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|
Add the following to your `rules.mk`: ### 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.
Add the following to your `config.h`:
|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|
## 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.
<!-- tabs:start -->
### ** 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 ```make
UNICODE_ENABLE = yes 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).
<br> ### ** Unicode Map **
### 1.2. Unicode Map :id=unicode-map 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.
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. To enable Unicode Map, add the following to your `rules.mk`:
Add the following to your `rules.mk`:
```make ```make
UNICODEMAP_ENABLE = yes UNICODEMAP_ENABLE = yes
``` ```
Then add `UM(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 ```c
enum unicode_names { enum unicode_names {
@ -51,242 +80,373 @@ enum unicode_names {
SNEK SNEK
}; };
const uint32_t unicode_map[] PROGMEM = { const uint32_t PROGMEM unicode_map[] = {
[BANG] = 0x203D, // ‽ [BANG] = 0x203D, // ‽
[IRONY] = 0x2E2E, // ⸮ [IRONY] = 0x2E2E, // ⸮
[SNEK] = 0x1F40D, // 🐍 [SNEK] = 0x1F40D, // 🐍
}; };
``` ```
Then you can use `UM(BANG)`, `UM(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 `UP(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 `UP()`. 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.
<br> 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 ```make
UCIS_ENABLE = yes UCIS_ENABLE = yes
``` ```
Then define a table like this in your keymap file: Then, create a mapping table in your `keymap.c`:
```c ```c
const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE( const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
UCIS_SYM("poop", 0x1F4A9), // 💩 UCIS_SYM("poop", 0x1F4A9), // 💩
UCIS_SYM("rofl", 0x1F923), // 🤣 UCIS_SYM("rofl", 0x1F923), // 🤣
UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺 UCIS_SYM("ukr", 0x1F1FA, 0x1F1E6), // 🇺🇦
UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0) // ಠ_ಠ 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 <!-- tabs:end -->
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. 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.
* `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.
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:
## 2. Input Modes :id=input-modes
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.
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).
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.
!> Using the _Unicode Hex Input_ input source may disable some Option-based shortcuts, such as Option+Left and Option+Right.
* **`UNICODE_MODE_LINUX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points).
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.
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)).
* **`UNICODE_MODE_WINDOWS`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`.
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.
* **`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).
* **`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).
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.
## 3. Setting the Input Mode :id=setting-the-input-mode
To set your desired input mode, add the following define to your `config.h`:
```c ```c
#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX #define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
// or
#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_WINCOMPOSE
``` ```
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)). 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.
You can also select multiple input modes, which allows you to easily cycle through them using the `UC_NEXT`/`UC_PREV` keycodes. 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`.
```c <!-- tabs:start -->
#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_LINUX, UNICODE_MODE_WINCOMPOSE
### ** macOS **
**Mode Name:** `UNICODE_MODE_MACOS`
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`.
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.
### ** Linux (IBus) **
**Mode Name:** `UNICODE_MODE_LINUX`
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.
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.
### ** Windows (WinCompose) **
**Mode Name:** `UNICODE_MODE_WINCOMPOSE`
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.
### ** Windows (HexNumpad) **
**Mode Name:** `UNICODE_MODE_WINDOWS`
!> 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 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.
To enable, run the following as an administrator, then reboot:
```
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 | ### ** BSD **
|----------------------------|---------|-------------------------|-----------------------------------------------------------------------------|
|`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`) |
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 <!-- tabs:end -->
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 ## API :id=api
#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
```
### `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 set_unicode_input_mode(uint8_t mode)` :id=api-set-unicode-input-mode
* `void unicode_input_finish(void)` This is called to exit Unicode input mode, for example by pressing Space or releasing the Alt key.
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 | ### `void unicode_input_mode_step_reverse(void)` : id=api-unicode-input-mode-step-reverse
|------------------|----------|------------------|-------------------------------------------|
|`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` |
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 - `uint8_t input_mode`
send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻"); 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. - **macOS**: Hold `UNICODE_KEY_MAC`
Ctrl+Alt+Win is not used very widely and should therefore be perfect for this. - **Linux**: Tap `UNICODE_KEY_LNX`
There is a macro defined for a mod-tab combo `LCAG_T`. - **WinCompose**: Tap `UNICODE_KEY_WINC`, then U
Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`. - **HexNumpad**: Hold Left Alt, then tap Numpad +
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. - **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.
<^<!<#a::Send, ä ---
<^<!<#<+a::Send, Ä
The hotkeys above are for the combination CtrlAltGui and CtrlAltGuiShift plus the letter a. ### `void unicode_input_finish(void)` :id=api-unicode-input-finish
AutoHotkey inserts the Text right of `Send, ` when this combination is pressed.
### US International Complete the Unicode input sequence. The exact behavior depends on the currently selected input mode:
If you enable the US International layout on the system, it will use punctuation to accent the characters. For instance, typing "\`a" will result in à. - **macOS**: Release `UNICODE_KEY_MAC`
You can find details on how to enable this [here](https://support.microsoft.com/en-us/help/17424/windows-change-keyboard-layout). - **Linux**: Tap Space
- **WinCompose**: Tap Enter
- **HexNumpad**: Release Left Alt
- **Emacs**: Tap Enter
## Software keyboard layout on Linux :id=custom-linux-layout This function is weakly defined, and can be overridden in user code.
This method does not require Unicode support on the keyboard itself but instead uses a custom keyboard layout for Xorg. This is how special characters are inserted by regular keyboards. This does not require IBus and works in practically all software. Help on creating a custom layout can be found [here](https://www.linux.com/news/creating-custom-keyboard-layouts-x11-using-xkb/), [here](http://karols.github.io/blog/2013/11/18/creating-custom-keyboard-layouts-for-linux/) and [here](https://wiki.archlinux.org/index.php/X_keyboard_extension). An example of how you could edit the `us` layout to gain 🤣 on `RALT(KC_R)`: ---
Edit the keyboard layout file `/usr/share/X11/xkb/symbols/us`. ### `void unicode_input_cancel(void)` :id=api-unicode-input-cancel
Inside `xkb_symbols "basic" {`, add `include "level3(ralt_switch)"`. Cancel the Unicode input sequence. The exact behavior depends on the currently selected input mode:
Find the line defining the R key and add an entry to the list, making it look like this: - **macOS**: Release `UNICODE_KEY_MAC`
``` - **Linux**: Tap Escape
key <AD04> { [ r, R, U1F923 ] }; - **WinCompose**: Tap Escape
``` - **HexNumpad**: Release Left Alt
- **Emacs**: Tap Ctrl+G
Save the file and run the command `setxkbmap us` to reload the layout. This function is weakly defined, and can be overridden in user code.
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. ---
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. ### `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
Send the code point(s) for the given UCIS index.
#### Arguments :id=api-register-ucis-arguments
- `uint8_t index`
The index into the UCIS symbol table.

View File

@ -1,5 +1,7 @@
# Userspace: Sharing Code Between Keymaps # 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, `<name>`) with the following structure: 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, `<name>`) with the following structure:
* `/users/<name>/` (added to the path automatically) * `/users/<name>/` (added to the path automatically)

View File

@ -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.

View File

@ -322,6 +322,29 @@ Flashing sequence:
3. Flash a .bin file 3. Flash a .bin file
4. Reset the device into application mode (may be done automatically) 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 <filename>
```
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 ## tinyuf2
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411. Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.

View File

@ -2,29 +2,29 @@
QMK has a GPIO control abstraction layer which is microcontroller agnostic. This is done to allow easy access to pin control across different platforms. QMK has a GPIO control abstraction layer which is microcontroller agnostic. This is done to allow easy access to pin control across different platforms.
## Functions :id=functions ## Macros :id=macros
The following functions provide basic control of GPIOs and are found in `platforms/<platform>/gpio.h`. The following macros provide basic control of GPIOs and are found in `platforms/<platform>/gpio.h`.
| Function | Description | Old AVR Examples | Old ChibiOS/ARM Examples | |Macro |Description |
|------------------------------|-----------------------------------------------------|-------------------------------------------------|--------------------------------------------------| |-------------------------------------|---------------------------------------------------------------------|
| `setPinInput(pin)` | Set pin as input with high impedance (High-Z) | `DDRB &= ~(1<<2)` | `palSetLineMode(pin, PAL_MODE_INPUT)` | |`gpio_set_pin_input(pin)` |Set pin as input with high impedance (High-Z) |
| `setPinInputHigh(pin)` | Set pin as input with builtin pull-up resistor | `DDRB &= ~(1<<2); PORTB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)` | |`gpio_set_pin_input_high(pin)` |Set pin as input with builtin pull-up resistor |
| `setPinInputLow(pin)` | Set pin as input with builtin pull-down resistor | N/A (Not supported on AVR) | `palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)` | |`gpio_set_pin_input_low(pin)` |Set pin as input with builtin pull-down resistor (unavailable on AVR)|
| `setPinOutput(pin)` | Set pin as output (alias of `setPinOutputPushPull`) | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` | |`gpio_set_pin_output(pin)` |Set pin as output (alias of `gpio_set_pin_output_push_pull`) |
| `setPinOutputPushPull(pin)` | Set pin as output, push/pull mode | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` | |`gpio_set_pin_output_push_pull(pin)` |Set pin as output, push/pull mode |
| `setPinOutputOpenDrain(pin)` | Set pin as output, open-drain mode | N/A (Not implemented on AVR) | `palSetLineMode(pin, PAL_MODE_OUTPUT_OPENDRAIN)` | |`gpio_set_pin_output_open_drain(pin)`|Set pin as output, open-drain mode (unavailable on AVR and ATSAM) |
| `writePinHigh(pin)` | Set pin level as high, assuming it is an output | `PORTB \|= (1<<2)` | `palSetLine(pin)` | |`gpio_write_pin_high(pin)` |Set pin level as high, assuming it is an output |
| `writePinLow(pin)` | Set pin level as low, assuming it is an output | `PORTB &= ~(1<<2)` | `palClearLine(pin)` | |`gpio_write_pin_low(pin)` |Set pin level as low, assuming it is an output |
| `writePin(pin, level)` | Set pin level, assuming it is an output | `(level) ? PORTB \|= (1<<2) : PORTB &= ~(1<<2)` | `(level) ? palSetLine(pin) : palClearLine(pin)` | |`gpio_write_pin(pin, level)` |Set pin level, assuming it is an output |
| `readPin(pin)` | Returns the level of the pin | `_SFR_IO8(pin >> 4) & _BV(pin & 0xF)` | `palReadLine(pin)` | |`gpio_read_pin(pin)` |Returns the level of the pin |
| `togglePin(pin)` | Invert pin level, assuming it is an output | `PORTB ^= (1<<2)` | `palToggleLine(pin)` | |`gpio_toggle_pin(pin)` |Invert pin level, assuming it is an output |
## Advanced Settings :id=advanced-settings ## Advanced Settings :id=advanced-settings
Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device and include any needed libraries. For AVR, the standard avr/io.h library is used; for STM32, the ChibiOS [PAL library](https://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used. Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device. For AVR, the standard `avr/io.h` library is used; for STM32, the ChibiOS [PAL library](https://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used.
## Atomic Operation ## Atomic Operation :id=atomic-operation
The above functions are not always guaranteed to work atomically. Therefore, if you want to prevent interruptions in the middle of operations when using multiple combinations of the above functions, use the following `ATOMIC_BLOCK_FORCEON` macro. The above functions are not always guaranteed to work atomically. Therefore, if you want to prevent interruptions in the middle of operations when using multiple combinations of the above functions, use the following `ATOMIC_BLOCK_FORCEON` macro.

View File

@ -169,11 +169,11 @@ The `post_rules.mk` file can interpret `features` of a keyboard-level before `co
ifeq ($(strip $(RGBLED_OPTION_TYPE)),backlight) ifeq ($(strip $(RGBLED_OPTION_TYPE)),backlight)
RGBLIGHT_ENABLE = yes RGBLIGHT_ENABLE = yes
OPT_DEFS += -DRGBLED_NUM=30 OPT_DEFS += -DRGBLIGHT_LED_COUNT=30
endif endif
ifeq ($(strip $(RGBLED_OPTION_TYPE)),underglow) ifeq ($(strip $(RGBLED_OPTION_TYPE)),underglow)
RGBLIGHT_ENABLE = yes RGBLIGHT_ENABLE = yes
OPT_DEFS += -DRGBLED_NUM=6 OPT_DEFS += -DRGBLIGHT_LED_COUNT=6
endif endif
``` ```

View File

@ -2,6 +2,18 @@
The I2C Master drivers used in QMK have a set of common functions to allow portability between MCUs. The I2C Master drivers used in QMK have a set of common functions to allow portability between MCUs.
## Usage :id=usage
In most cases, the I2C Master driver code is automatically included if you are using a feature or driver which requires it, such as [OLED](feature_oled_driver.md).
However, if you need to use the driver standalone, add the following to your `rules.mk`:
```make
I2C_DRIVER_REQUIRED = yes
```
You can then call the I2C API by including `i2c_master.h` in your code.
## I2C Addressing :id=note-on-i2c-addresses ## I2C Addressing :id=note-on-i2c-addresses
All of the addresses expected by this driver should be pushed to the upper 7 bits of the address byte. Setting All of the addresses expected by this driver should be pushed to the upper 7 bits of the address byte. Setting
@ -72,7 +84,7 @@ Configuration-wise, you'll need to set up the peripheral as per your MCU's datas
The following configuration values depend on the specific MCU in use. The following configuration values depend on the specific MCU in use.
### I2Cv1 :id=i2cv1 ### I2Cv1 :id=arm-configuration-i2cv1
* STM32F1xx * STM32F1xx
* STM32F2xx * STM32F2xx
@ -88,7 +100,7 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#7_I2Cv1_con
|`I2C1_CLOCK_SPEED` |`100000` | |`I2C1_CLOCK_SPEED` |`100000` |
|`I2C1_DUTY_CYCLE` |`STD_DUTY_CYCLE`| |`I2C1_DUTY_CYCLE` |`STD_DUTY_CYCLE`|
### I2Cv2 :id=i2cv2 ### I2Cv2 :id=arm-configuration-i2cv2
* STM32F0xx * STM32F0xx
* STM32F3xx * STM32F3xx
@ -105,9 +117,9 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#8_I2Cv2_I2C
|`I2C1_TIMINGR_SCLH` |`38U` | |`I2C1_TIMINGR_SCLH` |`38U` |
|`I2C1_TIMINGR_SCLL` |`129U` | |`I2C1_TIMINGR_SCLL` |`129U` |
## Functions :id=functions ## API :id=api
### `void i2c_init(void)` ### `void i2c_init(void)` :id=api-i2c-init
Initialize the I2C driver. This function must be called only once, before any of the below functions can be called. Initialize the I2C driver. This function must be called only once, before any of the below functions can be called.
@ -115,8 +127,8 @@ This function is weakly defined, meaning it can be overridden if necessary for y
```c ```c
void i2c_init(void) { void i2c_init(void) {
setPinInput(B6); // Try releasing special pins for a short time gpio_set_pin_input(B6); // Try releasing special pins for a short time
setPinInput(B7); gpio_set_pin_input(B7);
wait_ms(10); // Wait for the release to happen wait_ms(10); // Wait for the release to happen
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function
@ -126,9 +138,143 @@ void i2c_init(void) {
--- ---
### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` ### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
Start an I2C transaction. Send multiple bytes to the selected I2C device.
#### Arguments :id=api-i2c-transmit-arguments
- `uint8_t address`
The 7-bit I2C address of the device.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-transmit-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-receive
Receive multiple bytes from the selected I2C device.
#### Arguments :id=api-i2c-receive-arguments
- `uint8_t address`
The 7-bit I2C address of the device.
- `uint8_t *data`
A pointer to the buffer to read into.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-receive-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-write-register
Writes to a register with an 8-bit address on the I2C device.
#### Arguments :id=api-i2c-write-register-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint8_t regaddr`
The register address to write to.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-write-register-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-write-register16
Writes to a register with a 16-bit address (big endian) on the I2C device.
#### Arguments :id=api-i2c-write-register16-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint16_t regaddr`
The register address to write to.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-write-register16-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-read-register
Reads from a register with an 8-bit address on the I2C device.
#### Arguments :id=api-i2c-read-register-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint8_t regaddr`
The register address to read from.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-read-register-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-read-register16
Reads from a register with a 16-bit address (big endian) on the I2C device.
#### Arguments :id=api-i2c-read-register16-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint16_t regaddr`
The register address to read from.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value :id=api-i2c-read-register16-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout)` :id=api-i2c-ping-address
Pings the I2C bus for a specific address.
On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the requested address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsucessful response to ping attempt).
This function is weakly defined, meaning it can be overridden if necessary for your particular use case:
#### Arguments #### Arguments
@ -140,139 +286,3 @@ Start an I2C transaction.
#### Return Value #### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`. `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)`
Send multiple bytes to the selected I2C device.
#### Arguments
- `uint8_t address`
The 7-bit I2C address of the device.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)`
Receive multiple bytes from the selected I2C device.
#### Arguments
- `uint8_t address`
The 7-bit I2C address of the device.
- `uint8_t *data`
A pointer to the buffer to read into.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
Writes to a register with an 8-bit address on the I2C device.
#### Arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint8_t regaddr`
The register address to write to.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
Writes to a register with a 16-bit address (big endian) on the I2C device.
#### Arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint16_t regaddr`
The register address to write to.
- `uint8_t *data`
A pointer to the data to transmit.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
Reads from a register with an 8-bit address on the I2C device.
#### Arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint8_t regaddr`
The register address to read from.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
Reads from a register with a 16-bit address (big endian) on the I2C device.
#### Arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
- `uint16_t regaddr`
The register address to read from.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
#### Return Value
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
### `i2c_status_t i2c_stop(void)`
Stop the current I2C transaction.

View File

@ -112,7 +112,6 @@
* [分割キーボード](ja/feature_split_keyboard.md) * [分割キーボード](ja/feature_split_keyboard.md)
* [速記](ja/feature_stenography.md) * [速記](ja/feature_stenography.md)
* [感熱式プリンタ](ja/feature_thermal_printer.md) * [感熱式プリンタ](ja/feature_thermal_printer.md)
* [Velocikey](ja/feature_velocikey.md)
* QMK の開発 * QMK の開発
* [PR チェックリスト](ja/pr_checklist.md) * [PR チェックリスト](ja/pr_checklist.md)

View File

@ -248,7 +248,7 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
* high/low ピンを使って左右を決定します。low = 右手、high = 左手。`B7` を使っているピンに置き換えます。これはオプションで、`SPLIT_HAND_PIN` が未定義のままである場合、EE_HANDS メソッドまたは標準の Let's Splitが使っている MASTER_LEFT / MASTER_RIGHT 定義をまだ使うことができます。 * high/low ピンを使って左右を決定します。low = 右手、high = 左手。`B7` を使っているピンに置き換えます。これはオプションで、`SPLIT_HAND_PIN` が未定義のままである場合、EE_HANDS メソッドまたは標準の Let's Splitが使っている MASTER_LEFT / MASTER_RIGHT 定義をまだ使うことができます。
* `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>` * `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>`
* 左右はキーマトリックスのキースイッチが存在しない交点を使って決定されます。通常、この交点が短絡している(ローレベル)のときに左側と見なされます。もし `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT` が定義されている場合は、ローレベルの時に右側と決定されます。 * 左右はキーマトリックスのキースイッチが存在しない交点を使って決定されます。通常、この交点が短絡している(ローレベル)のときに右側と見なされます。もし `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_LEFT` が定義されている場合は、ローレベルの時に左側と決定されます。
* `#define EE_HANDS` (`SPLIT_HAND_PIN` と `SPLIT_HAND_MATRIX_GRID` が定義されていない場合のみ動作します) * `#define EE_HANDS` (`SPLIT_HAND_PIN` と `SPLIT_HAND_MATRIX_GRID` が定義されていない場合のみ動作します)
* `eeprom-lefthand.eep`/`eeprom-righthand.eep` がそれぞれの半分に書き込まれた後で、EEPROM 内に格納されている左右の設定の値を読み込みます。 * `eeprom-lefthand.eep`/`eeprom-righthand.eep` がそれぞれの半分に書き込まれた後で、EEPROM 内に格納されている左右の設定の値を読み込みます。

View File

@ -110,11 +110,11 @@ enum my_keycodes {
開発環境をセットアップした場合は、プルリクエストを開く前に以下のコマンドを `qmk_firmware/` フォルダから実行することで、あなたの変更をプレビューすることができます: 開発環境をセットアップした場合は、プルリクエストを開く前に以下のコマンドを `qmk_firmware/` フォルダから実行することで、あなたの変更をプレビューすることができます:
./bin/qmk docs qmk docs
または、Python 3 のみがインストールされている場合: または、Python 3 のみがインストールされている場合:
python3 -m http.server 8936 python3 -m http.server 8936 --directory docs
その後、ウェブブラウザで、`http://localhost:8936/` を表示します。 その後、ウェブブラウザで、`http://localhost:8936/` を表示します。

View File

@ -109,8 +109,8 @@ QMK が完全な `info.json` を生成するときはいつでも、`config.h`
パズルの最後のピースは、ビルドシステムに新しいオプションを提供することです。 パズルの最後のピースは、ビルドシステムに新しいオプションを提供することです。
これは、2つのファイルを生成することによって行われます。 これは、2つのファイルを生成することによって行われます。
* `.build/obj_<keyboard>/src/info_config.h` * `.build/obj_<keyboard>_<keymap>/src/info_config.h`
* `.build/obj_<keyboard>/src/rules.mk` * `.build/obj_<keyboard>_<keymap>/src/rules.mk`
この2つのファイルは、次のコードによって生成されます。 この2つのファイルは、次のコードによって生成されます。

Some files were not shown because too many files have changed in this diff Show More