Merge branch 'master' of github.com:qmk/qmk_firmware
This commit is contained in:
commit
e324166a81
4
.clangd
Normal file
4
.clangd
Normal file
@ -0,0 +1,4 @@
|
||||
CompileFlags:
|
||||
Add: [-Wno-unknown-attributes, -Wno-maybe-uninitialized, -Wno-unknown-warning-option]
|
||||
Remove: [-W*, -mcall-prologues]
|
||||
Compiler: clang
|
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@ -40,3 +40,7 @@ translation:
|
||||
- docs/ru-ru/**/*
|
||||
CI:
|
||||
- .github/**/*
|
||||
dd:
|
||||
- data/constants/**/*
|
||||
- data/mappings/**/*
|
||||
- data/schemas/**/*
|
||||
|
4
.github/workflows/api.yml
vendored
4
.github/workflows/api.yml
vendored
@ -19,13 +19,13 @@ on:
|
||||
jobs:
|
||||
api_data:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
# protect against those who work in their fork on 'important' branches
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
5
.github/workflows/auto_tag.yml
vendored
5
.github/workflows/auto_tag.yml
vendored
@ -4,6 +4,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@ -26,12 +27,12 @@ jobs:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Bump version and push tag
|
||||
uses: anothrNick/github-tag-action@1.61.0
|
||||
uses: anothrNick/github-tag-action@1.66.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DEFAULT_BUMP: 'patch'
|
||||
|
74
.github/workflows/ci_builds.yml
vendored
Normal file
74
.github/workflows/ci_builds.yml
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
name: CI Builds
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, develop]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
type: choice
|
||||
description: 'Branch to build'
|
||||
options: [master, develop]
|
||||
|
||||
concurrency: ci_build-${{ github.event.inputs.branch || github.ref_name }}
|
||||
|
||||
jobs:
|
||||
ci_builds:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
name: "CI Build"
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 1380
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
keymap: [default, via]
|
||||
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.event.inputs.branch || github.ref }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip3 install -r requirements.txt
|
||||
|
||||
- name: Run `qmk mass-compile` (keymap ${{ matrix.keymap }})
|
||||
run: |
|
||||
export NCPUS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null)
|
||||
qmk mass-compile -t -j $NCPUS -km ${{ matrix.keymap }} -e DUMP_CI_METADATA=yes || touch .failed
|
||||
# Generate the step summary markdown
|
||||
./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
|
||||
# Truncate to a maximum of 1MB to deal with GitHub workflow limit
|
||||
truncate --size='<960K' $GITHUB_STEP_SUMMARY || true
|
||||
# Exit with failure if the compilation stage failed
|
||||
[ ! -f .failed ] || exit 1
|
||||
|
||||
- name: 'Upload artifacts'
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: artifacts-${{ github.event.inputs.branch || github.ref_name }}-${{ matrix.keymap }}
|
||||
if-no-files-found: ignore
|
||||
path: |
|
||||
*.bin
|
||||
*.hex
|
||||
*.uf2
|
||||
.build/failed.*
|
||||
|
||||
- name: 'CI Discord Notification'
|
||||
if: always()
|
||||
working-directory: util/ci/
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.CI_DISCORD_WEBHOOK }}
|
||||
run: |
|
||||
python3 -m pip install -r requirements.txt
|
||||
python3 ./discord-results.py --branch ${{ github.event.inputs.branch || github.ref_name }} --keymap ${{ matrix.keymap }} --url ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
4
.github/workflows/cli.yml
vendored
4
.github/workflows/cli.yml
vendored
@ -18,13 +18,13 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
2
.github/workflows/develop_update.yml
vendored
2
.github/workflows/develop_update.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
@ -17,13 +17,13 @@ on:
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
# protect against those who develop with their fork on master
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
@ -37,7 +37,7 @@ jobs:
|
||||
qmk --verbose generate-docs
|
||||
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BASE_BRANCH: master
|
||||
|
3
.github/workflows/feature_branch_update.yml
vendored
3
.github/workflows/feature_branch_update.yml
vendored
@ -18,9 +18,10 @@ jobs:
|
||||
matrix:
|
||||
branch:
|
||||
- xap
|
||||
- riot
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
6
.github/workflows/format.yml
vendored
6
.github/workflows/format.yml
vendored
@ -19,13 +19,13 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
- name: Get changed files
|
||||
id: file_changes
|
||||
uses: tj-actions/changed-files@v35
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: Run qmk formatters
|
||||
shell: 'bash {0}'
|
||||
|
6
.github/workflows/format_push.yml
vendored
6
.github/workflows/format_push.yml
vendored
@ -13,13 +13,13 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
git config user.email 'hello@qmk.fm'
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
if: ${{ github.repository == 'qmk/qmk_firmware'}}
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
|
36
.github/workflows/lint.yml
vendored
36
.github/workflows/lint.yml
vendored
@ -12,13 +12,13 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
- name: Get changed files
|
||||
id: file_changes
|
||||
uses: tj-actions/changed-files@v35
|
||||
uses: tj-actions/changed-files@v39
|
||||
|
||||
- name: Print info
|
||||
run: |
|
||||
@ -36,6 +36,7 @@ jobs:
|
||||
echo '${{ steps.file_changes.outputs.all_changed_files}}'
|
||||
|
||||
- name: Run qmk lint
|
||||
if: always()
|
||||
shell: 'bash {0}'
|
||||
run: |
|
||||
QMK_CHANGES=$(echo -e '${{ steps.file_changes.outputs.all_changed_files}}' | sed 's/ /\n/g')
|
||||
@ -72,3 +73,32 @@ jobs:
|
||||
exit 255
|
||||
fi
|
||||
exit $exit_code
|
||||
|
||||
- name: Verify at most one added keyboard
|
||||
if: always()
|
||||
shell: 'bash {0}'
|
||||
run: |
|
||||
git reset --hard
|
||||
git clean -xfd
|
||||
|
||||
# Get the keyboard list and count for the target branch
|
||||
git checkout -f ${{ github.base_ref }}
|
||||
git pull --ff-only
|
||||
QMK_KEYBOARDS_BASE=$(qmk list-keyboards)
|
||||
QMK_KEYBOARDS_BASE_COUNT=$(qmk list-keyboards | wc -l)
|
||||
|
||||
# Get the keyboard list and count for the PR
|
||||
git checkout -f ${{ github.head_ref }}
|
||||
git merge --no-commit --squash ${{ github.base_ref }}
|
||||
QMK_KEYBOARDS_PR=$(qmk list-keyboards)
|
||||
QMK_KEYBOARDS_PR_COUNT=$(qmk list-keyboards | wc -l)
|
||||
|
||||
echo "::group::Keyboards changes in this PR"
|
||||
diff -d -U 0 <(echo "$QMK_KEYBOARDS_BASE") <(echo "$QMK_KEYBOARDS_PR") | grep -vE '^(---|\+\+\+|@@)' | sed -e 's@^-@Removed: @g' -e 's@^+@ Added: @g'
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $QMK_KEYBOARDS_PR_COUNT -gt $(($QMK_KEYBOARDS_BASE_COUNT + 1)) ]]; then
|
||||
echo "More than one keyboard added in this PR -- see the PR Checklist."
|
||||
echo "::error::More than one keyboard added in this PR -- see the PR Checklist."
|
||||
exit 1
|
||||
fi
|
||||
|
4
.github/workflows/regen.yml
vendored
4
.github/workflows/regen.yml
vendored
@ -13,13 +13,13 @@ jobs:
|
||||
regen:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run qmk generators
|
||||
run: |
|
||||
|
6
.github/workflows/regen_push.yml
vendored
6
.github/workflows/regen_push.yml
vendored
@ -13,13 +13,13 @@ jobs:
|
||||
regen:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run qmk generators
|
||||
run: |
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
git config user.email 'hello@qmk.fm'
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
if: ${{ github.repository == 'qmk/qmk_firmware'}}
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v7
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
4
.github/workflows/unit_test.yml
vendored
4
.github/workflows/unit_test.yml
vendored
@ -23,10 +23,10 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/qmk_cli
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install dependencies
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -30,6 +30,9 @@ quantum/version.h
|
||||
*.qmk
|
||||
*.uf2
|
||||
|
||||
# DD config at wrong location
|
||||
/keyboards/**/keymaps/*/info.json
|
||||
|
||||
# Old-style QMK Makefiles
|
||||
/keyboards/**/Makefile
|
||||
|
||||
@ -45,7 +48,6 @@ quantum/version.h
|
||||
.idea/
|
||||
.project
|
||||
.settings/
|
||||
.vagrant/
|
||||
|
||||
# ?
|
||||
.dep
|
||||
@ -93,6 +95,7 @@ secrets.tar
|
||||
# Python things
|
||||
__pycache__
|
||||
.python-version
|
||||
.venv
|
||||
|
||||
# Prerequisites for updating ChibiOS
|
||||
/util/fmpp*
|
||||
|
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@ -3,7 +3,7 @@
|
||||
"recommendations": [
|
||||
"EditorConfig.EditorConfig",
|
||||
"xaver.clang-format",
|
||||
"ms-vscode.cpptools",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"bierner.github-markdown-preview",
|
||||
"donjayamanne.git-extension-pack"
|
||||
]
|
||||
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -26,6 +26,9 @@
|
||||
},
|
||||
"python.formatting.provider": "yapf",
|
||||
"[json]": {
|
||||
"editor.formatOnSave": false
|
||||
}
|
||||
"editor.formatOnSave": false
|
||||
},
|
||||
"clangd.arguments": [
|
||||
"--header-insertion=never"
|
||||
]
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
FROM qmkfm/qmk_cli
|
||||
|
||||
VOLUME /qmk_firmware
|
||||
WORKDIR /qmk_firmware
|
||||
|
||||
CMD qmk compile -kb all -km default
|
2
Makefile
2
Makefile
@ -328,7 +328,7 @@ define PARSE_TEST
|
||||
ifeq ($$(TEST_NAME),all)
|
||||
MATCHED_TESTS := $$(TEST_LIST)
|
||||
else
|
||||
MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),))
|
||||
MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring x$$(TEST_NAME)x, x$$(notdir $$(TEST))x), $$(TEST),))
|
||||
endif
|
||||
$$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
|
||||
endef
|
||||
|
95
Vagrantfile
vendored
95
Vagrantfile
vendored
@ -1,95 +0,0 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
Vagrant.configure(2) do |config|
|
||||
# define a name instead of just 'default'
|
||||
config.vm.define "qmk_firmware"
|
||||
|
||||
# VMware/Virtualbox ( and also Hyperv/Parallels) 64 bit
|
||||
config.vm.box = "generic/debian10"
|
||||
|
||||
config.vm.synced_folder '.', '/vagrant'
|
||||
|
||||
# This section allows you to customize the Virtualbox VM
|
||||
# settings, ie showing the GUI or upping the memory
|
||||
# or cores if desired
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
# Hide the VirtualBox GUI when booting the machine
|
||||
vb.gui = false
|
||||
# Uncomment the below lines if you want to program
|
||||
# your Teensy via the VM rather than your host OS
|
||||
#vb.customize ['modifyvm', :id, '--usb', 'on']
|
||||
#vb.customize ['usbfilter', 'add', '0',
|
||||
# '--target', :id,
|
||||
# '--name', 'teensy',
|
||||
# '--vendorid', '0x16c0',
|
||||
# '--productid','0x0478'
|
||||
# ]
|
||||
# Customize the amount of memory on the VM:
|
||||
vb.memory = "512"
|
||||
# Uncomment the below lines if you have time sync
|
||||
# issues with make and incremental builds
|
||||
#vb.customize [ "guestproperty", "set", :id, "/VirtualBox/GuestAdd/VBoxService/--timesync-set-threshold", 1000 ]
|
||||
end
|
||||
|
||||
# This section allows you to customize the VMware VM
|
||||
# settings, ie showing the GUI or upping the memory
|
||||
# or cores if desired
|
||||
config.vm.provider "vmware_workstation" do |vmw|
|
||||
# Hide the VMware GUI when booting the machine
|
||||
vmw.gui = false
|
||||
|
||||
# Customize the amount of memory on the VM:
|
||||
vmw.memory = "512"
|
||||
end
|
||||
|
||||
config.vm.provider "vmware_fusion" do |vmf|
|
||||
# Hide the vmfare GUI when booting the machine
|
||||
vmf.gui = false
|
||||
|
||||
# Customize the amount of memory on the VM:
|
||||
vmf.memory = "512"
|
||||
end
|
||||
|
||||
# Docker provider pulls from hub.docker.com respecting docker.image if
|
||||
# config.vm.box is nil. In this case, we adhoc build util/vagrant/Dockerfile.
|
||||
# Note that this bind-mounts from the current dir to
|
||||
# /vagrant in the guest, so unless your UID is 1000 to match vagrant in the
|
||||
# image, you'll need to: chmod -R a+rw .
|
||||
config.vm.provider "docker" do |docker, override|
|
||||
override.vm.box = nil
|
||||
docker.build_dir = "util/vagrant"
|
||||
docker.has_ssh = true
|
||||
end
|
||||
|
||||
# Unless we are running the docker container directly
|
||||
# 1. run container detached on vm
|
||||
# 2. attach on 'vagrant ssh'
|
||||
["virtualbox", "vmware_workstation", "vmware_fusion"].each do |type|
|
||||
config.vm.provider type do |virt, override|
|
||||
override.vm.provision "docker" do |d|
|
||||
d.run "qmkfm/qmk_cli",
|
||||
cmd: "tail -f /dev/null",
|
||||
args: "--privileged -v /dev:/dev -v '/vagrant:/vagrant'"
|
||||
end
|
||||
|
||||
override.vm.provision "shell", inline: <<-SHELL
|
||||
echo 'docker restart qmkfm-qmk_cli && exec docker exec -it qmkfm-qmk_cli /bin/bash -l' >> ~vagrant/.bashrc
|
||||
SHELL
|
||||
end
|
||||
end
|
||||
|
||||
config.vm.post_up_message = <<-EOT
|
||||
|
||||
Log into the environment using 'vagrant ssh'. QMK directory synchronized with
|
||||
host is located at /vagrant
|
||||
To compile the .hex files use make command inside this directory, e.g.
|
||||
cd /vagrant
|
||||
make <keyboard>:default
|
||||
|
||||
Examples:
|
||||
make planck/rev4:default:dfu
|
||||
make planck/rev4:default
|
||||
|
||||
EOT
|
||||
end
|
@ -17,7 +17,6 @@ $(TEST)_INC := \
|
||||
tests/test_common/common_config.h
|
||||
|
||||
$(TEST)_SRC := \
|
||||
$(TMK_COMMON_SRC) \
|
||||
$(QUANTUM_SRC) \
|
||||
$(SRC) \
|
||||
$(QUANTUM_PATH)/keymap_introspection.c \
|
||||
@ -31,7 +30,7 @@ $(TEST)_SRC := \
|
||||
tests/test_common/test_logger.cpp \
|
||||
$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
|
||||
|
||||
$(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
|
||||
$(TEST)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
|
||||
|
||||
$(TEST)_CONFIG := $(TEST_PATH)/config.h
|
||||
|
||||
|
@ -27,7 +27,11 @@ QMK_BIN ?= qmk
|
||||
# Set the filename for the final firmware binary
|
||||
KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD))
|
||||
TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP)
|
||||
KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
|
||||
|
||||
ifeq ($(strip $(DUMP_CI_METADATA)),yes)
|
||||
$(info CI Metadata: KEYBOARD=$(KEYBOARD))
|
||||
$(info CI Metadata: KEYMAP=$(KEYMAP))
|
||||
endif
|
||||
|
||||
# Force expansion
|
||||
TARGET := $(TARGET)
|
||||
@ -39,7 +43,7 @@ endif
|
||||
# Object files and generated keymap directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
|
||||
INTERMEDIATE_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
|
||||
|
||||
ifdef SKIP_VERSION
|
||||
OPT_DEFS += -DSKIP_VERSION
|
||||
@ -55,7 +59,7 @@ VERSION_H_FLAGS += --skip-git
|
||||
endif
|
||||
|
||||
# Generate the board's version.h file.
|
||||
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(KEYMAP_OUTPUT)/src/version.h)
|
||||
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(INTERMEDIATE_OUTPUT)/src/version.h)
|
||||
|
||||
# Determine which subfolders exist.
|
||||
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD)
|
||||
@ -116,7 +120,7 @@ MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP)
|
||||
MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
|
||||
|
||||
# Pull in rules from info.json
|
||||
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_rules.mk)
|
||||
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_rules.mk)
|
||||
include $(INFO_RULES_MK)
|
||||
|
||||
# Check for keymap.json first, so we can regenerate keymap.c
|
||||
@ -156,28 +160,28 @@ endif
|
||||
|
||||
# Have we found a keymap.json?
|
||||
ifneq ("$(wildcard $(KEYMAP_JSON))", "")
|
||||
KEYMAP_C := $(KEYMAP_OUTPUT)/src/keymap.c
|
||||
KEYMAP_H := $(KEYMAP_OUTPUT)/src/config.h
|
||||
KEYMAP_C := $(INTERMEDIATE_OUTPUT)/src/keymap.c
|
||||
KEYMAP_H := $(INTERMEDIATE_OUTPUT)/src/config.h
|
||||
|
||||
# Load the keymap-level rules.mk if exists
|
||||
-include $(KEYMAP_PATH)/rules.mk
|
||||
|
||||
# Load any rules.mk content from keymap.json
|
||||
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --output $(KEYMAP_OUTPUT)/src/rules.mk $(KEYMAP_JSON))
|
||||
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --output $(INTERMEDIATE_OUTPUT)/src/rules.mk $(KEYMAP_JSON))
|
||||
include $(INFO_RULES_MK)
|
||||
|
||||
# Add rules to generate the keymap files - indentation here is important
|
||||
$(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
|
||||
$(INTERMEDIATE_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON)
|
||||
$(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/config.h $(INTERMEDIATE_OUTPUT)/src/keymap.c
|
||||
|
||||
endif
|
||||
|
||||
@ -318,25 +322,34 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","")
|
||||
INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json
|
||||
endif
|
||||
|
||||
CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h
|
||||
KEYBOARD_SRC += $(KEYBOARD_OUTPUT)/src/default_keyboard.c
|
||||
CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
|
||||
KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
|
||||
|
||||
$(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
|
||||
$(INTERMEDIATE_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h)
|
||||
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_config.h)
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(KEYBOARD_OUTPUT)/src/default_keyboard.c: $(INFO_JSON_FILES)
|
||||
$(INTERMEDIATE_OUTPUT)/src/default_keyboard.c: $(INFO_JSON_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.c)
|
||||
$(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c)
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES)
|
||||
$(INTERMEDIATE_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h)
|
||||
$(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h)
|
||||
@$(BUILD_CMD)
|
||||
|
||||
generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.c $(KEYBOARD_OUTPUT)/src/default_keyboard.h
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/info_config.h $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h
|
||||
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/info_deps.d
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/info_deps.d:
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-make-dependencies -kb $(KEYBOARD) -km $(KEYMAP) -o $(INTERMEDIATE_OUTPUT)/src/info_deps.d)
|
||||
@$(BUILD_CMD)
|
||||
|
||||
-include $(INTERMEDIATE_OUTPUT)/src/info_deps.d
|
||||
|
||||
.INTERMEDIATE : generated-files
|
||||
|
||||
@ -409,8 +422,7 @@ VPATH += $(KEYMAP_PATH)
|
||||
VPATH += $(USER_PATH)
|
||||
VPATH += $(KEYBOARD_PATHS)
|
||||
VPATH += $(COMMON_VPATH)
|
||||
VPATH += $(KEYBOARD_OUTPUT)/src
|
||||
VPATH += $(KEYMAP_OUTPUT)/src
|
||||
VPATH += $(INTERMEDIATE_OUTPUT)/src
|
||||
|
||||
include $(BUILDDEFS_PATH)/common_features.mk
|
||||
include $(BUILDDEFS_PATH)/generic_features.mk
|
||||
@ -419,19 +431,17 @@ include $(PLATFORM_PATH)/common.mk
|
||||
|
||||
SRC += $(patsubst %.c,%.clib,$(LIB_SRC))
|
||||
SRC += $(patsubst %.c,%.clib,$(QUANTUM_LIB_SRC))
|
||||
SRC += $(TMK_COMMON_SRC)
|
||||
OPT_DEFS += $(TMK_COMMON_DEFS)
|
||||
EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
|
||||
|
||||
-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/bootloader.mk
|
||||
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
|
||||
-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk
|
||||
|
||||
ifneq ($(strip $(PROTOCOL)),)
|
||||
include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk
|
||||
PROTOCOL_KEY = $(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]'))
|
||||
else
|
||||
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
|
||||
PROTOCOL_KEY = $(PLATFORM_KEY)
|
||||
endif
|
||||
include $(TMK_PATH)/protocol/$(PROTOCOL_KEY)/$(PROTOCOL_KEY).mk
|
||||
|
||||
# Setup definitions based on the selected MCU
|
||||
$(eval $(call add_qmk_prefix_defs,MCU_ORIG,MCU))
|
||||
@ -441,6 +451,14 @@ $(eval $(call add_qmk_prefix_defs,MCU_FAMILY,MCU_FAMILY))
|
||||
$(eval $(call add_qmk_prefix_defs,MCU_SERIES,MCU_SERIES))
|
||||
$(eval $(call add_qmk_prefix_defs,BOARD,BOARD))
|
||||
|
||||
# Control whether intermediate file listings are generated
|
||||
# e.g.:
|
||||
# make handwired/onekey/blackpill_f411:default KEEP_INTERMEDIATES=yes
|
||||
# cat .build/obj_handwired_onekey_blackpill_f411_default/quantum/quantum.i | sed -e 's@^#.*@@g' -e 's@^\s*//.*@@g' -e '/^\s*$/d' | clang-format
|
||||
ifeq ($(strip $(KEEP_INTERMEDIATES)), yes)
|
||||
OPT_DEFS += -save-temps=obj
|
||||
endif
|
||||
|
||||
# TODO: remove this bodge?
|
||||
PROJECT_DEFS := $(OPT_DEFS)
|
||||
PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS)
|
||||
@ -449,17 +467,14 @@ PROJECT_CONFIG := $(CONFIG_H)
|
||||
CONFIG_H += $(POST_CONFIG_H)
|
||||
ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H)
|
||||
|
||||
OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT)
|
||||
$(KEYMAP_OUTPUT)_SRC := $(SRC)
|
||||
$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \
|
||||
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(KEYBOARD_OUTPUT)/src/default_keyboard.h\" \
|
||||
-DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\"
|
||||
$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS)
|
||||
$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H)
|
||||
$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC)
|
||||
$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS)
|
||||
$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC)
|
||||
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
|
||||
OUTPUTS := $(INTERMEDIATE_OUTPUT)
|
||||
$(INTERMEDIATE_OUTPUT)_SRC := $(SRC) $(PLATFORM_SRC)
|
||||
$(INTERMEDIATE_OUTPUT)_DEFS := $(OPT_DEFS) \
|
||||
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(INTERMEDIATE_OUTPUT)/src/default_keyboard.h\" \
|
||||
-DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" \
|
||||
$(PROJECT_DEFS)
|
||||
$(INTERMEDIATE_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(PROJECT_INC)
|
||||
$(INTERMEDIATE_OUTPUT)_CONFIG := $(CONFIG_H) $(PROJECT_CONFIG)
|
||||
|
||||
# Default target.
|
||||
all: build check-size
|
||||
|
@ -75,6 +75,10 @@ $(TEST)_SRC += \
|
||||
tests/test_common/main.cpp \
|
||||
$(QUANTUM_PATH)/logging/print.c
|
||||
|
||||
ifneq ($(strip $(INTROSPECTION_KEYMAP_C)),)
|
||||
$(TEST)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
|
||||
endif
|
||||
|
||||
$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
|
||||
$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
|
||||
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
|
||||
|
@ -134,7 +134,7 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/mousekey.c
|
||||
endif
|
||||
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3360 pmw3389 pimoroni_trackball custom
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
|
||||
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
|
||||
@ -213,10 +213,10 @@ else
|
||||
SRC += eeprom_driver.c eeprom_spi.c
|
||||
else ifeq ($(strip $(EEPROM_DRIVER)), legacy_stm32_flash)
|
||||
# STM32 Emulated EEPROM, backed by MCU flash (soon to be deprecated)
|
||||
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_FLASH_EMULATED
|
||||
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_LEGACY_EMULATED_FLASH
|
||||
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
|
||||
COMMON_VPATH += $(DRIVER_PATH)/flash
|
||||
SRC += eeprom_driver.c eeprom_stm32.c flash_stm32.c
|
||||
SRC += eeprom_driver.c eeprom_legacy_emulated_flash.c legacy_flash_ops.c
|
||||
else ifeq ($(strip $(EEPROM_DRIVER)), transient)
|
||||
# Transient EEPROM implementation -- no data storage but provides runtime area for it
|
||||
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
|
||||
@ -317,14 +317,10 @@ ifneq ($(strip $(FLASH_DRIVER)), none)
|
||||
endif
|
||||
|
||||
RGBLIGHT_ENABLE ?= no
|
||||
VALID_RGBLIGHT_TYPES := WS2812 APA102 custom
|
||||
|
||||
ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
|
||||
RGBLIGHT_DRIVER ?= custom
|
||||
endif
|
||||
VALID_RGBLIGHT_TYPES := ws2812 apa102 custom
|
||||
|
||||
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
RGBLIGHT_DRIVER ?= WS2812
|
||||
RGBLIGHT_DRIVER ?= ws2812
|
||||
|
||||
ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
|
||||
@ -338,11 +334,11 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
RGB_KEYCODES_ENABLE := yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812)
|
||||
ifeq ($(strip $(RGBLIGHT_DRIVER)), ws2812)
|
||||
WS2812_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102)
|
||||
ifeq ($(strip $(RGBLIGHT_DRIVER)), apa102)
|
||||
APA102_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
|
||||
@ -352,8 +348,8 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
endif
|
||||
|
||||
LED_MATRIX_ENABLE ?= no
|
||||
VALID_LED_MATRIX_TYPES := IS31FL3731 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 custom
|
||||
# TODO: IS31FL3733 IS31FL3737 IS31FL3741
|
||||
VALID_LED_MATRIX_TYPES := is31fl3731 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 custom
|
||||
# TODO: is31fl3733 is31fl3737 is31fl3741
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
||||
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
|
||||
@ -367,48 +363,49 @@ endif
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners
|
||||
POST_CONFIG_H += $(QUANTUM_DIR)/led_matrix/post_config.h
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
|
||||
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
|
||||
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
|
||||
CIE1931_CURVE := yes
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3731)
|
||||
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3731-simple.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3742A)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3743A)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3743a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3745)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3745)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3746A)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3746a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), CKLED2001)
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), ckled2001)
|
||||
OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||
SRC += ckled2001-simple.c
|
||||
@ -419,7 +416,7 @@ endif
|
||||
|
||||
RGB_MATRIX_ENABLE ?= no
|
||||
|
||||
VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 WS2812 custom
|
||||
VALID_RGB_MATRIX_TYPES := aw20216 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 ws2812 custom
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
|
||||
@ -432,6 +429,7 @@ endif
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners
|
||||
POST_CONFIG_H += $(QUANTUM_DIR)/rgb_matrix/post_config.h
|
||||
SRC += $(QUANTUM_DIR)/color.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
|
||||
@ -439,82 +437,89 @@ endif
|
||||
CIE1931_CURVE := yes
|
||||
RGB_KEYCODES_ENABLE := yes
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), aw20216)
|
||||
OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||
SRC += aw20216.c
|
||||
QUANTUM_LIB_SRC += spi_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3731)
|
||||
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3731.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3733)
|
||||
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3733.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3736)
|
||||
OPT_DEFS += -DIS31FL3736 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3736.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3737)
|
||||
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3737.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3741)
|
||||
OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31fl3741.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3742A)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3742a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3743A)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3743a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3745)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3745)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3746A)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3746a)
|
||||
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led/issi
|
||||
SRC += is31flcommon.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), ckled2001)
|
||||
OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||
SRC += ckled2001.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
|
||||
OPT_DEFS += -DWS2812
|
||||
WS2812_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102)
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), apa102)
|
||||
OPT_DEFS += -DAPA102
|
||||
APA102_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
@ -558,23 +563,23 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
|
||||
endif
|
||||
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/backlight
|
||||
COMMON_VPATH += $(DRIVER_PATH)/backlight
|
||||
SRC += $(QUANTUM_DIR)/backlight/backlight.c
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
|
||||
OPT_DEFS += -DBACKLIGHT_ENABLE
|
||||
|
||||
ifeq ($(strip $(BACKLIGHT_DRIVER)), custom)
|
||||
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
||||
else
|
||||
ifneq ($(strip $(BACKLIGHT_DRIVER)), custom)
|
||||
SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c
|
||||
ifeq ($(strip $(BACKLIGHT_DRIVER)), pwm)
|
||||
SRC += $(QUANTUM_DIR)/backlight/backlight_$(PLATFORM_KEY).c
|
||||
|
||||
ifeq ($(strip $(BACKLIGHT_DRIVER)), software)
|
||||
SRC += $(DRIVER_PATH)/backlight/backlight_software.c
|
||||
else
|
||||
SRC += $(QUANTUM_DIR)/backlight/backlight_$(strip $(BACKLIGHT_DRIVER)).c
|
||||
SRC += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/backlight_$(strip $(BACKLIGHT_DRIVER)).c
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c vendor
|
||||
VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
|
||||
|
||||
WS2812_DRIVER ?= bitbang
|
||||
ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
|
||||
@ -584,15 +589,11 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
|
||||
|
||||
OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
|
||||
ifeq ($(strip $(WS2812_DRIVER)), bitbang)
|
||||
SRC += ws2812.c
|
||||
else
|
||||
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
|
||||
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
|
||||
|
||||
ifeq ($(strip $(PLATFORM)), CHIBIOS)
|
||||
ifeq ($(strip $(WS2812_DRIVER)), pwm)
|
||||
OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
|
||||
endif
|
||||
ifeq ($(strip $(PLATFORM)), CHIBIOS)
|
||||
ifeq ($(strip $(WS2812_DRIVER)), pwm)
|
||||
OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -718,18 +719,23 @@ ifeq ($(strip $(FNV_ENABLE)), yes)
|
||||
SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
|
||||
endif
|
||||
|
||||
VALID_HAPTIC_DRIVER_TYPES := drv2605l solenoid
|
||||
ifeq ($(strip $(HAPTIC_ENABLE)),yes)
|
||||
COMMON_VPATH += $(DRIVER_PATH)/haptic
|
||||
ifeq ($(filter $(HAPTIC_DRIVER),$(VALID_HAPTIC_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid HAPTIC_DRIVER,HAPTIC_DRIVER="$(HAPTIC_DRIVER)" is not a valid Haptic driver)
|
||||
else
|
||||
COMMON_VPATH += $(DRIVER_PATH)/haptic
|
||||
|
||||
ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), )
|
||||
SRC += DRV2605L.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
OPT_DEFS += -DDRV2605L
|
||||
endif
|
||||
ifeq ($(strip $(HAPTIC_DRIVER)), drv2605l)
|
||||
SRC += drv2605l.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
OPT_DEFS += -DHAPTIC_DRV2605L
|
||||
endif
|
||||
|
||||
ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), )
|
||||
SRC += solenoid.c
|
||||
OPT_DEFS += -DSOLENOID_ENABLE
|
||||
ifeq ($(strip $(HAPTIC_DRIVER)), solenoid)
|
||||
SRC += solenoid.c
|
||||
OPT_DEFS += -DHAPTIC_SOLENOID
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -739,19 +745,30 @@ ifeq ($(strip $(HD44780_ENABLE)), yes)
|
||||
SRC += hd44780.c
|
||||
endif
|
||||
|
||||
VALID_OLED_DRIVER_TYPES := SSD1306 custom
|
||||
OLED_DRIVER ?= SSD1306
|
||||
VALID_OLED_DRIVER_TYPES := custom ssd1306
|
||||
OLED_DRIVER ?= ssd1306
|
||||
VALID_OLED_TRANSPORT_TYPES := i2c spi custom
|
||||
OLED_TRANSPORT ?= i2c
|
||||
ifeq ($(strip $(OLED_ENABLE)), yes)
|
||||
ifeq ($(filter $(OLED_DRIVER),$(VALID_OLED_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid OLED_DRIVER,OLED_DRIVER="$(OLED_DRIVER)" is not a valid OLED driver)
|
||||
else
|
||||
OPT_DEFS += -DOLED_ENABLE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/oled
|
||||
ifeq ($(filter $(OLED_TRANSPORT),$(VALID_OLED_TRANSPORT_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid OLED_TRANSPORT,OLED_TRANSPORT="$(OLED_TRANSPORT)" is not a valid OLED transport)
|
||||
else
|
||||
OPT_DEFS += -DOLED_ENABLE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/oled
|
||||
ifneq ($(strip $(OLED_DRIVER)), custom)
|
||||
SRC += oled_driver.c
|
||||
endif
|
||||
|
||||
OPT_DEFS += -DOLED_DRIVER_$(strip $(shell echo $(OLED_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
ifeq ($(strip $(OLED_DRIVER)), SSD1306)
|
||||
SRC += ssd1306_sh1106.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
OPT_DEFS += -DOLED_TRANSPORT_$(strip $(shell echo $(OLED_TRANSPORT) | tr '[:lower:]' '[:upper:]'))
|
||||
ifeq ($(strip $(OLED_TRANSPORT)), i2c)
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
ifeq ($(strip $(OLED_TRANSPORT)), spi)
|
||||
QUANTUM_LIB_SRC += spi_master.c
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@ -767,13 +784,15 @@ endif
|
||||
ifeq ($(strip $(UCIS_ENABLE)), yes)
|
||||
OPT_DEFS += -DUCIS_ENABLE
|
||||
UNICODE_COMMON := yes
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c \
|
||||
$(QUANTUM_DIR)/unicode/ucis.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
|
||||
OPT_DEFS += -DUNICODEMAP_ENABLE
|
||||
UNICODE_COMMON := yes
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c \
|
||||
$(QUANTUM_DIR)/unicode/unicodemap.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(UNICODE_ENABLE)), yes)
|
||||
@ -813,9 +832,9 @@ endif
|
||||
|
||||
ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
|
||||
PS2_ENABLE := yes
|
||||
MOUSE_ENABLE := yes
|
||||
SRC += ps2_mouse.c
|
||||
OPT_DEFS += -DPS2_MOUSE_ENABLE
|
||||
OPT_DEFS += -DMOUSE_ENABLE
|
||||
endif
|
||||
|
||||
VALID_PS2_DRIVER_TYPES := busywait interrupt usart vendor
|
||||
@ -884,7 +903,7 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
|
||||
endif
|
||||
|
||||
BLUETOOTH_ENABLE ?= no
|
||||
VALID_BLUETOOTH_DRIVER_TYPES := BluefruitLE RN42 custom
|
||||
VALID_BLUETOOTH_DRIVER_TYPES := bluefruit_le custom rn42
|
||||
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
|
||||
ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid BLUETOOTH_DRIVER,BLUETOOTH_DRIVER="$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type)
|
||||
@ -892,17 +911,19 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
|
||||
OPT_DEFS += -DBLUETOOTH_ENABLE
|
||||
NO_USB_STARTUP_CHECK := yes
|
||||
COMMON_VPATH += $(DRIVER_PATH)/bluetooth
|
||||
SRC += outputselect.c bluetooth.c
|
||||
SRC += outputselect.c
|
||||
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE)
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), bluefruit_le)
|
||||
OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE
|
||||
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
|
||||
SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
|
||||
QUANTUM_LIB_SRC += analog.c
|
||||
QUANTUM_LIB_SRC += spi_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42)
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), rn42)
|
||||
OPT_DEFS += -DBLUETOOTH_RN42 -DHAL_USE_SERIAL=TRUE
|
||||
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
|
||||
SRC += $(DRIVER_PATH)/bluetooth/rn42.c
|
||||
QUANTUM_LIB_SRC += uart.c
|
||||
endif
|
||||
|
@ -152,6 +152,7 @@ endif
|
||||
# To produce a UF2 file in your build, add to your keyboard's rules.mk:
|
||||
# FIRMWARE_FORMAT = uf2
|
||||
UF2CONV = $(TOP_DIR)/util/uf2conv.py
|
||||
UF2CONV_ARGS ?=
|
||||
UF2_FAMILY ?= 0x0
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
@ -175,7 +176,7 @@ MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
|
||||
|
||||
# For a ChibiOS build, ensure that the board files have the hook overrides injected
|
||||
define BOARDSRC_INJECT_HOOKS
|
||||
$(KEYBOARD_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h
|
||||
$(INTERMEDIATE_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h
|
||||
endef
|
||||
$(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ))))
|
||||
|
||||
@ -219,7 +220,7 @@ gccversion :
|
||||
@$(BUILD_CMD)
|
||||
|
||||
%.uf2: %.elf
|
||||
$(eval CMD=$(HEX) $< $(BUILD_DIR)/$(TARGET).tmp && $(UF2CONV) $(BUILD_DIR)/$(TARGET).tmp --output $@ --convert --family $(UF2_FAMILY) >/dev/null 2>&1)
|
||||
$(eval CMD=$(HEX) $< $(BUILD_DIR)/$(TARGET).tmp && $(UF2CONV) $(UF2CONV_ARGS) $(BUILD_DIR)/$(TARGET).tmp --output $@ --convert --family $(UF2_FAMILY) >/dev/null 2>&1)
|
||||
#@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n"
|
||||
@$(SILENT) || printf "$(MSG_UF2) $@" | $(AWK_CMD)
|
||||
@$(BUILD_CMD)
|
||||
@ -391,6 +392,8 @@ check-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 \
|
||||
$(REMOVE) $(TARGET).$(FIRMWARE_FORMAT); \
|
||||
$(REMOVE) $(BUILD_DIR)/$(TARGET).{hex,bin,uf2}; \
|
||||
printf "\n * $(MSG_FILE_TOO_BIG)"; $(PRINT_ERROR_PLAIN); \
|
||||
else \
|
||||
if [ $(FREE_SIZE) -lt $(SIZE_MARGIN) ]; then \
|
||||
|
@ -7,7 +7,12 @@ endif
|
||||
|
||||
# TODO: opt in rather than assume everything uses a pro micro
|
||||
PIN_COMPATIBLE ?= promicro
|
||||
|
||||
# Remove whitespace from any rule.mk provided vars
|
||||
# - env cannot be overwritten but cannot have whitespace anyway
|
||||
CONVERT_TO:=$(strip $(CONVERT_TO))
|
||||
ifneq ($(CONVERT_TO),)
|
||||
|
||||
# stash so we can overwrite env provided vars if needed
|
||||
ACTIVE_CONVERTER=$(CONVERT_TO)
|
||||
|
||||
@ -23,13 +28,13 @@ ifneq ($(CONVERT_TO),)
|
||||
TARGET := $(TARGET)_$(CONVERT_TO)
|
||||
|
||||
# Configure any defaults
|
||||
OPT_DEFS += -DCONVERT_TO_$(strip $(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]'))
|
||||
OPT_DEFS += -DCONVERTER_TARGET=\"$(strip $(CONVERT_TO))\"
|
||||
OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]')
|
||||
OPT_DEFS += -DCONVERTER_TARGET=\"$(CONVERT_TO)\"
|
||||
OPT_DEFS += -DCONVERTER_ENABLED
|
||||
VPATH += $(CONVERTER)
|
||||
|
||||
# Configure for "alias" - worst case it produces an idential define
|
||||
OPT_DEFS += -DCONVERT_TO_$(strip $(shell echo $(ACTIVE_CONVERTER) | tr '[:lower:]' '[:upper:]'))
|
||||
OPT_DEFS += -DCONVERT_TO_$(shell echo $(ACTIVE_CONVERTER) | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Finally run any converter specific logic
|
||||
include $(CONVERTER)/converter.mk
|
||||
|
@ -32,6 +32,7 @@ GENERIC_FEATURES = \
|
||||
KEY_OVERRIDE \
|
||||
LEADER \
|
||||
PROGRAMMABLE_BUTTON \
|
||||
REPEAT_KEY \
|
||||
SECURE \
|
||||
SPACE_CADET \
|
||||
SWAP_HANDS \
|
||||
|
@ -17,7 +17,7 @@ HARDWARE_OPTION_NAMES = \
|
||||
BACKLIGHT_ENABLE \
|
||||
BACKLIGHT_DRIVER \
|
||||
RGBLIGHT_ENABLE \
|
||||
RGBLIGHT_CUSTOM_DRIVER \
|
||||
RGBLIGHT_DRIVER \
|
||||
RGB_MATRIX_ENABLE \
|
||||
RGB_MATRIX_DRIVER \
|
||||
CIE1931_CURVE \
|
||||
@ -60,7 +60,6 @@ OTHER_OPTION_NAMES = \
|
||||
ENCODER_ENABLE_CUSTOM \
|
||||
GERMAN_ENABLE \
|
||||
HAPTIC_ENABLE \
|
||||
HHKB_RN42_ENABLE \
|
||||
ISSI_ENABLE \
|
||||
KEYLOGGER_ENABLE \
|
||||
LCD_BACKLIGHT_ENABLE \
|
||||
@ -85,7 +84,8 @@ OTHER_OPTION_NAMES = \
|
||||
SECURE_ENABLE \
|
||||
CAPS_WORD_ENABLE \
|
||||
AUTOCORRECT_ENABLE \
|
||||
TRI_LAYER_ENABLE
|
||||
TRI_LAYER_ENABLE \
|
||||
REPEAT_KEY_ENABLE
|
||||
|
||||
define NAME_ECHO
|
||||
@printf " %-30s = %-16s # %s\\n" "$1" "$($1)" "$(origin $1)"
|
||||
|
@ -253,7 +253,7 @@
|
||||
"0x002F": {
|
||||
"group": "basic",
|
||||
"key": "KC_LEFT_BRACKET",
|
||||
"label": "]",
|
||||
"label": "[",
|
||||
"aliases": [
|
||||
"KC_LBRC"
|
||||
]
|
||||
@ -261,7 +261,7 @@
|
||||
"0x0030": {
|
||||
"group": "basic",
|
||||
"key": "KC_RIGHT_BRACKET",
|
||||
"label": "[",
|
||||
"label": "]",
|
||||
"aliases": [
|
||||
"KC_RBRC"
|
||||
]
|
||||
@ -1512,4 +1512,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
data/constants/keycodes/keycodes_0.0.3_quantum.hjson
Normal file
18
data/constants/keycodes/keycodes_0.0.3_quantum.hjson
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"keycodes": {
|
||||
"0x7C79": {
|
||||
"group": "quantum",
|
||||
"key": "QK_REPEAT_KEY",
|
||||
"aliases": [
|
||||
"QK_REP"
|
||||
]
|
||||
},
|
||||
"0x7C7A": {
|
||||
"group": "quantum",
|
||||
"key": "QK_ALT_REPEAT_KEY",
|
||||
"aliases": [
|
||||
"QK_AREP"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
"blok": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
"board": "QMK_BLOK"
|
||||
},
|
||||
"michi": {
|
||||
"processor": "RP2040",
|
||||
@ -74,6 +74,11 @@
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"liatris": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,95 +10,130 @@
|
||||
// deprecated: Default `false`. Set to `true` to turn on warning when a value exists
|
||||
// invalid: Default `false`. Set to `true` to generate errors when a value exists
|
||||
// replace_with: use with a key marked deprecated or invalid to designate a replacement
|
||||
|
||||
// APA102
|
||||
"APA102_CI_PIN": {"info_key": "apa102.clock_pin"},
|
||||
"APA102_DEFAULT_BRIGHTNESS": {"info_key": "apa102.default_brightness", "value_type": "int"},
|
||||
"APA102_DI_PIN": {"info_key": "apa102.data_pin"},
|
||||
|
||||
// Audio
|
||||
"AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "bool"},
|
||||
"SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "bool"},
|
||||
|
||||
// Backlight
|
||||
"BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "bool"},
|
||||
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
|
||||
"BACKLIGHT_CAPS_LOCK": {"info_key": "backlight.as_caps_lock", "value_type": "bool"},
|
||||
"BACKLIGHT_LEVELS": {"info_key": "backlight.levels", "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_PIN": {"info_key": "backlight.pin"},
|
||||
"BACKLIGHT_PINS": {"info_key": "backlight.pins", "value_type": "array"},
|
||||
"BOOTMAGIC_LITE_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"},
|
||||
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
|
||||
|
||||
// Bootmagic
|
||||
"BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"},
|
||||
"BOOTMAGIC_LITE_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"},
|
||||
"BOOTMAGIC_LITE_COLUMN_RIGHT": {"info_key": "split.bootmagic.matrix.1", "value_type": "int"},
|
||||
"BOOTMAGIC_LITE_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"},
|
||||
"BOOTMAGIC_LITE_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"},
|
||||
|
||||
// Caps Word
|
||||
"BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "bool"},
|
||||
"CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"},
|
||||
"COMBO_COUNT": {"info_key": "combo.count", "value_type": "int"},
|
||||
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
|
||||
"DEBOUNCE": {"info_key": "debounce", "value_type": "int"},
|
||||
"DIODE_DIRECTION": {"info_key": "diode_direction"},
|
||||
"CAPS_WORD_INVERT_ON_SHIFT": {"info_key": "caps_word.invert_on_shift", "value_type": "bool"},
|
||||
"DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.double_tap_shift_turns_on", "value_type": "bool"},
|
||||
"FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "bool"},
|
||||
|
||||
// Combos
|
||||
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
|
||||
|
||||
// Dynamic Keymap
|
||||
"DYNAMIC_KEYMAP_EEPROM_MAX_ADDR": {"info_key": "dynamic_keymap.eeprom_max_addr", "value_type": "int"},
|
||||
"DYNAMIC_KEYMAP_LAYER_COUNT": {"info_key": "dynamic_keymap.layer_count", "value_type": "int"},
|
||||
"HOLD_ON_OTHER_KEY_PRESS": {"info_key": "tapping.hold_on_other_key_press", "value_type": "bool"},
|
||||
"HOLD_ON_OTHER_KEY_PRESS_PER_KEY": {"info_key": "tapping.hold_on_other_key_press_per_key", "value_type": "bool"},
|
||||
"LAYOUTS": {"info_key": "layout_aliases", "value_type": "mapping"},
|
||||
"LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "bool"},
|
||||
"LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "bool"},
|
||||
"LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"},
|
||||
|
||||
// Indicators
|
||||
"LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"},
|
||||
"LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"},
|
||||
"LED_SCROLL_LOCK_PIN": {"info_key": "indicators.scroll_lock"},
|
||||
"LED_COMPOSE_PIN": {"info_key": "indicators.compose"},
|
||||
"LED_KANA_PIN": {"info_key": "indicators.kana"},
|
||||
"LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"},
|
||||
|
||||
// Leader Key
|
||||
"LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "bool"},
|
||||
"LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "bool"},
|
||||
"LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"},
|
||||
|
||||
// LED Matrix
|
||||
"LED_MATRIX_CENTER": {"info_key": "led_matrix.center_point", "value_type": "array.int"},
|
||||
"LED_MATRIX_MAXIMUM_BRIGHTNESS": {"info_key": "led_matrix.max_brightness", "value_type": "int"},
|
||||
"LED_MATRIX_SPD_STEP": {"info_key": "led_matrix.speed_steps", "value_type": "int"},
|
||||
"LED_MATRIX_SPLIT": {"info_key": "led_matrix.split_count", "value_type": "array.int"},
|
||||
"LED_MATRIX_TIMEOUT": {"info_key": "led_matrix.timeout", "value_type": "int"},
|
||||
"LED_MATRIX_HUE_STEP": {"info_key": "led_matrix.hue_steps", "value_type": "int"},
|
||||
"LED_MATRIX_SAT_STEP": {"info_key": "led_matrix.sat_steps", "value_type": "int"},
|
||||
"LED_MATRIX_VAL_STEP": {"info_key": "led_matrix.val_steps", "value_type": "int"},
|
||||
"LED_MATRIX_SPD_STEP": {"info_key": "led_matrix.speed_steps", "value_type": "int"},
|
||||
"LED_MATRIX_LED_COUNT": {"info_key": "led_matrix.led_count", "value_type": "int", "to_json": false},
|
||||
|
||||
// LUFA Bootloader
|
||||
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
|
||||
"QMK_ESC_OUTPUT": {"info_key": "qmk_lufa_bootloader.esc_output"},
|
||||
"QMK_LED": {"info_key": "qmk_lufa_bootloader.led"},
|
||||
"QMK_SPEAKER": {"info_key": "qmk_lufa_bootloader.speaker"},
|
||||
|
||||
// Matrix
|
||||
"DEBOUNCE": {"info_key": "debounce", "value_type": "int"},
|
||||
"DIODE_DIRECTION": {"info_key": "diode_direction"},
|
||||
"MATRIX_HAS_GHOST": {"info_key": "matrix_pins.ghost", "value_type": "bool"},
|
||||
"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"},
|
||||
|
||||
// Mouse Keys
|
||||
"MOUSEKEY_DELAY": {"info_key": "mousekey.delay", "value_type": "int"},
|
||||
"MOUSEKEY_INTERVAL": {"info_key": "mousekey.interval", "value_type": "int"},
|
||||
"MOUSEKEY_MAX_SPEED": {"info_key": "mousekey.max_speed", "value_type": "int"},
|
||||
"MOUSEKEY_TIME_TO_MAX": {"info_key": "mousekey.time_to_max", "value_type": "int"},
|
||||
"MOUSEKEY_WHEEL_DELAY": {"info_key": "mousekey.wheel_delay", "value_type": "int"},
|
||||
|
||||
// One Shot
|
||||
"ONESHOT_TIMEOUT": {"info_key": "oneshot.timeout", "value_type": "int"},
|
||||
"ONESHOT_TAP_TOGGLE": {"info_key": "oneshot.tap_toggle", "value_type": "int"},
|
||||
"PERMISSIVE_HOLD": {"info_key": "tapping.permissive_hold", "value_type": "bool"},
|
||||
"PERMISSIVE_HOLD_PER_KEY": {"info_key": "tapping.permissive_hold_per_key", "value_type": "bool"},
|
||||
|
||||
// PS/2
|
||||
"PS2_CLOCK_PIN": {"info_key": "ps2.clock_pin"},
|
||||
"PS2_DATA_PIN": {"info_key": "ps2.data_pin"},
|
||||
"RETRO_TAPPING": {"info_key": "tapping.retro", "value_type": "bool"},
|
||||
"RETRO_TAPPING_PER_KEY": {"info_key": "tapping.retro_per_key", "value_type": "bool"},
|
||||
"RGB_DI_PIN": {"info_key": "rgblight.pin"},
|
||||
|
||||
// RGB Matrix
|
||||
"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_MAXIMUM_BRIGHTNESS": {"info_key": "rgb_matrix.max_brightness", "value_type": "int"},
|
||||
"RGB_MATRIX_SAT_STEP": {"info_key": "rgb_matrix.sat_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_SPD_STEP": {"info_key": "rgb_matrix.speed_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_SPLIT": {"info_key": "rgb_matrix.split_count", "value_type": "array.int"},
|
||||
"RGB_MATRIX_TIMEOUT": {"info_key": "rgb_matrix.timeout", "value_type": "int"},
|
||||
"RGB_MATRIX_VAL_STEP": {"info_key": "rgb_matrix.val_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_LED_COUNT": {"info_key": "rgb_matrix.led_count", "value_type": "int", "to_json": false},
|
||||
|
||||
// RGBLight
|
||||
"RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"},
|
||||
"RGBLED_SPLIT": {"info_key": "rgblight.split_count", "value_type": "array.int"},
|
||||
"RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"},
|
||||
"RGBLIGHT_LAYER_BLINK": {"info_key": "rgblight.layers.blink", "value_type": "bool"},
|
||||
"RGBLIGHT_LAYERS": {"info_key": "rgblight.layers.enabled", "value_type": "bool"},
|
||||
"RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF": {"info_key": "rgblight.layers.override_rgb", "value_type": "bool"},
|
||||
"RGBLIGHT_LED_MAP": {"info_key": "rgblight.led_map", "value_type": "array.int"},
|
||||
"RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"},
|
||||
"RGBLIGHT_MAX_LAYERS": {"info_key": "rgblight.layers.max", "value_type": "int"},
|
||||
"RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"},
|
||||
"RGBLIGHT_SAT_STEP": {"info_key": "rgblight.saturation_steps", "value_type": "int"},
|
||||
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
|
||||
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"},
|
||||
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"},
|
||||
"RGB_MATRIX_CENTER": {"info_key": "rgb_matrix.center_point", "value_type": "array.int"},
|
||||
"RGB_MATRIX_MAXIMUM_BRIGHTNESS": {"info_key": "rgb_matrix.max_brightness", "value_type": "int"},
|
||||
"RGB_MATRIX_SPLIT": {"info_key": "rgb_matrix.split_count", "value_type": "array.int"},
|
||||
"RGB_MATRIX_TIMEOUT": {"info_key": "rgb_matrix.timeout", "value_type": "int"},
|
||||
"RGB_MATRIX_HUE_STEP": {"info_key": "rgb_matrix.hue_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_SAT_STEP": {"info_key": "rgb_matrix.sat_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_VAL_STEP": {"info_key": "rgb_matrix.val_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_SPD_STEP": {"info_key": "rgb_matrix.speed_steps", "value_type": "int"},
|
||||
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
|
||||
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
|
||||
"QMK_ESC_OUTPUT": {"info_key": "qmk_lufa_bootloader.esc_output"},
|
||||
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
|
||||
"QMK_LED": {"info_key": "qmk_lufa_bootloader.led"},
|
||||
"QMK_SPEAKER": {"info_key": "qmk_lufa_bootloader.speaker"},
|
||||
|
||||
// Secure
|
||||
"SECURE_IDLE_TIMEOUT": {"info_key": "secure.idle_timeout", "value_type": "int"},
|
||||
"SECURE_UNLOCK_SEQUENCE": {"info_key": "secure.unlock_sequence", "value_type": "array.array.int", "to_json": false},
|
||||
"SECURE_UNLOCK_TIMEOUT": {"info_key": "secure.unlock_timeout", "value_type": "int"},
|
||||
"SECURE_IDLE_TIMEOUT": {"info_key": "secure.idle_timeout", "value_type": "int"},
|
||||
"SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "bool"},
|
||||
|
||||
// Split Keyboard
|
||||
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
|
||||
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
|
||||
"SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"},
|
||||
"SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"},
|
||||
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
|
||||
@ -106,35 +141,53 @@
|
||||
"SPLIT_USB_TIMEOUT_POLL": {"info_key": "split.usb_detect.polling_interval", "value_type": "int"},
|
||||
"SPLIT_WATCHDOG_ENABLE": {"info_key": "split.transport.watchdog", "value_type": "bool"},
|
||||
"SPLIT_WATCHDOG_TIMEOUT": {"info_key": "split.transport.watchdog_timeout", "value_type": "int"},
|
||||
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
|
||||
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
|
||||
|
||||
// Tapping
|
||||
"HOLD_ON_OTHER_KEY_PRESS": {"info_key": "tapping.hold_on_other_key_press", "value_type": "bool"},
|
||||
"HOLD_ON_OTHER_KEY_PRESS_PER_KEY": {"info_key": "tapping.hold_on_other_key_press_per_key", "value_type": "bool"},
|
||||
"PERMISSIVE_HOLD": {"info_key": "tapping.permissive_hold", "value_type": "bool"},
|
||||
"PERMISSIVE_HOLD_PER_KEY": {"info_key": "tapping.permissive_hold_per_key", "value_type": "bool"},
|
||||
"RETRO_TAPPING": {"info_key": "tapping.retro", "value_type": "bool"},
|
||||
"RETRO_TAPPING_PER_KEY": {"info_key": "tapping.retro_per_key", "value_type": "bool"},
|
||||
"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"},
|
||||
"TAPPING_TERM": {"info_key": "tapping.term", "value_type": "int"},
|
||||
"TAPPING_TERM_PER_KEY": {"info_key": "tapping.term_per_key", "value_type": "bool"},
|
||||
"TAPPING_TOGGLE": {"info_key": "tapping.toggle", "value_type": "int"},
|
||||
|
||||
// USB
|
||||
"FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "bool"},
|
||||
"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_SUSPEND_WAKEUP_DELAY": {"info_key": "usb.suspend_wakeup_delay", "value_type": "int"},
|
||||
|
||||
// WS2812
|
||||
"WS2812_DI_PIN": {"info_key": "ws2812.pin"},
|
||||
"WS2812_I2C_ADDRESS": {"info_key": "ws2812.i2c_address", "value_type": "hex"},
|
||||
"WS2812_I2C_TIMEOUT": {"info_key": "ws2812.i2c_timeout", "value_type": "int"},
|
||||
|
||||
"LAYOUTS": {"info_key": "layout_aliases", "value_type": "mapping"},
|
||||
|
||||
// Items we want flagged in lint
|
||||
"NO_ACTION_MACRO": {"info_key": "_invalid.no_action_macro", "invalid": true},
|
||||
"NO_ACTION_FUNCTION": {"info_key": "_invalid.no_action_function", "invalid": true},
|
||||
"DESCRIPTION": {"info_key": "_invalid.usb_description", "invalid": true},
|
||||
"DEBOUNCING_DELAY": {"info_key": "_invalid.debouncing_delay", "invalid": true, "replace_with": "DEBOUNCE"},
|
||||
"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_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true}
|
||||
"NO_ACTION_FUNCTION": {"info_key": "_invalid.no_action_function", "invalid": true},
|
||||
"NO_ACTION_MACRO": {"info_key": "_invalid.no_action_macro", "invalid": true},
|
||||
"PREVENT_STUCK_MODIFIERS": {"info_key": "_invalid.prevent_stuck_mods", "invalid": true},
|
||||
"UNUSED_PINS": {"info_key": "_invalid.unused_pins", "deprecated": true},
|
||||
"RGBLIGHT_ANIMATIONS": {"info_key": "_invalid.rgblight.animations.all", "value_type": "bool", "invalid": 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"},
|
||||
"RGBLIGHT_ANIMATIONS": {"info_key": "_invalid.rgblight.animations.all", "value_type": "bool", "invalid": true},
|
||||
"TAPPING_FORCE_HOLD": {"info_key": "tapping.force_hold", "value_type": "bool", "deprecated": true},
|
||||
"TAPPING_FORCE_HOLD_PER_KEY": {"info_key": "tapping.force_hold_per_key", "value_type": "bool", "deprecated": true},
|
||||
"IGNORE_MOD_TAP_INTERRUPT": {"info_key": "_deprecated.ignore_mod_tap_interrupt", "value_type": "bool", "deprecated": true},
|
||||
"IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "_invalid.ignore_mod_tap_interrupt_per_key", "invalid": true}
|
||||
"UNUSED_PINS": {"info_key": "_invalid.unused_pins", "deprecated": true},
|
||||
"COMBO_COUNT": {"info_key": "_invalid.combo.count", "invalid": true},
|
||||
|
||||
// USB params, need to mark as failure when specified in config.h, rather than deprecated
|
||||
"DEVICE_VER": {"info_key": "usb.device_version", "value_type": "bcd_version", "deprecated": true, "replace_with": "`usb.device_version` in info.json"},
|
||||
"MANUFACTURER": {"info_key": "manufacturer", "value_type": "str", "deprecated": true, "replace_with": "`manufacturer` 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"},
|
||||
"VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.vid` in info.json"},
|
||||
"PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false, "value_type": "str", "deprecated": true, "replace_with": "`keyboard_name` in info.json"},
|
||||
"MANUFACTURER": {"info_key": "manufacturer", "value_type": "str", "deprecated": true, "replace_with": "`manufacturer` in info.json"},
|
||||
"DEVICE_VER": {"info_key": "usb.device_version", "value_type": "bcd_version", "deprecated": true, "replace_with": "`usb.device_version` in info.json"}
|
||||
}
|
||||
|
@ -10,36 +10,39 @@
|
||||
// deprecated: Default `false`. Set to `true` to turn on warning when a value exists
|
||||
// invalid: Default `false`. Set to `true` to generate errors when a value exists
|
||||
// replace_with: use with a key marked deprecated or invalid to designate a replacement
|
||||
|
||||
"BACKLIGHT_DRIVER": {"info_key": "backlight.driver"},
|
||||
"BLUETOOTH_DRIVER": {"info_key": "bluetooth.driver"},
|
||||
"BOARD": {"info_key": "board"},
|
||||
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
|
||||
"BOOTMAGIC_ENABLE": {"info_key": "bootmagic.enabled", "value_type": "bool"},
|
||||
"BLUETOOTH_DRIVER": {"info_key": "bluetooth.driver"},
|
||||
"BACKLIGHT_DRIVER": {"info_key": "backlight.driver"},
|
||||
"CAPS_WORD_ENABLE": {"info_key": "caps_word.enabled", "value_type": "bool"},
|
||||
"DEBOUNCE_TYPE": {"info_key": "build.debounce_type"},
|
||||
"EEPROM_DRIVER": {"info_key": "eeprom.driver"},
|
||||
"ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
|
||||
"FIRMWARE_FORMAT": {"info_key": "build.firmware_format"},
|
||||
"KEYBOARD_SHARED_EP": {"info_key": "usb.shared_endpoint.keyboard", "value_type": "bool"},
|
||||
"MOUSE_SHARED_EP": {"info_key": "usb.shared_endpoint.mouse", "value_type": "bool"},
|
||||
"LAYOUTS": {"info_key": "community_layouts", "value_type": "list"},
|
||||
"LED_MATRIX_DRIVER": {"info_key": "led_matrix.driver"},
|
||||
"RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"},
|
||||
"LTO_ENABLE": {"info_key": "build.lto", "value_type": "bool"},
|
||||
"MCU": {"info_key": "processor", "warn_duplicate": false},
|
||||
"MOUSE_SHARED_EP": {"info_key": "usb.shared_endpoint.mouse", "value_type": "bool"},
|
||||
"MOUSEKEY_ENABLE": {"info_key": "mouse_key.enabled", "value_type": "bool"},
|
||||
"NO_USB_STARTUP_CHECK": {"info_key": "usb.no_startup_check", "value_type": "bool"},
|
||||
"PIN_COMPATIBLE": {"info_key": "pin_compatible"},
|
||||
"PLATFORM_KEY": {"info_key": "platform_key", "to_json": false},
|
||||
"PS2_DRIVER": {"info_key": "ps2.driver"},
|
||||
"PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
|
||||
"PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
|
||||
"RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"},
|
||||
"RGBLIGHT_DRIVER": {"info_key": "rgblight.driver"},
|
||||
"SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"},
|
||||
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
|
||||
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false},
|
||||
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"},
|
||||
"STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"},
|
||||
"STENO_PROTOCOL": {"info_key": "stenography.protocol"},
|
||||
"PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
|
||||
"PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
|
||||
"PS2_DRIVER": {"info_key": "ps2.driver"},
|
||||
|
||||
"PLATFORM_KEY": {"info_key": "platform_key", "to_json": false},
|
||||
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"},
|
||||
"WS2812_DRIVER": {"info_key": "ws2812.driver"},
|
||||
|
||||
// Items we want flagged in lint
|
||||
"CTPC": {"info_key": "_deprecated.ctpc", "deprecated": true, "replace_with": "CONVERT_TO=proton_c"},
|
||||
|
@ -1,13 +1,9 @@
|
||||
{
|
||||
// Format for each entry:
|
||||
// "<alias>": {
|
||||
// "target": "<keyboard_folder>",
|
||||
// "layouts": {
|
||||
// "<layout_alias>": "<layout_target>"
|
||||
// }
|
||||
// "target": "<keyboard_folder>"
|
||||
// }
|
||||
//
|
||||
// Both target and layouts are optional.
|
||||
"2_milk": {
|
||||
"target": "spaceman/2_milk"
|
||||
},
|
||||
@ -41,6 +37,9 @@
|
||||
"angel64": {
|
||||
"target": "angel64/alpha"
|
||||
},
|
||||
"ashpil/modelm_usbc": {
|
||||
"target": "ibm/model_m/ashpil_usbc"
|
||||
},
|
||||
"at101_blackheart": {
|
||||
"target": "viktus/at101_bh"
|
||||
},
|
||||
@ -113,6 +112,15 @@
|
||||
"cmm_studio/saka68": {
|
||||
"target": "cmm_studio/saka68/solder"
|
||||
},
|
||||
"converter/modelm101": {
|
||||
"target": "ibm/model_m/teensypp"
|
||||
},
|
||||
"converter/modelm101_teensy2": {
|
||||
"target": "ibm/model_m/teensy2"
|
||||
},
|
||||
"converter/modelm_ssk": {
|
||||
"target": "ibm/model_m_ssk/teensypp_ssk"
|
||||
},
|
||||
"cospad": {
|
||||
"target": "kprepublic/cospad"
|
||||
},
|
||||
@ -128,27 +136,21 @@
|
||||
"daisy": {
|
||||
"target": "ktec/daisy"
|
||||
},
|
||||
"doro67/multi": {
|
||||
"layouts": {
|
||||
"LAYOUT_ansi": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
},
|
||||
"doro67/regular": {
|
||||
"layouts": {
|
||||
"LAYOUT": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
},
|
||||
"doro67/rgb": {
|
||||
"layouts": {
|
||||
"LAYOUT": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
},
|
||||
"drakon": {
|
||||
"target": "jagdpietr/drakon"
|
||||
},
|
||||
"durgod/k320": {
|
||||
"target": "durgod/k3x0/k320"
|
||||
},
|
||||
"durgod/hades": {
|
||||
"target": "durgod/dgk6x/hades_ansi"
|
||||
},
|
||||
"durgod/hades_ansi": {
|
||||
"target": "durgod/dgk6x/hades_ansi"
|
||||
},
|
||||
"durgod/hades_iso": {
|
||||
"target": "durgod/dgk6x/hades_iso"
|
||||
},
|
||||
"dztech/dz60rgb": {
|
||||
"target": "dztech/dz60rgb/v1"
|
||||
},
|
||||
@ -191,12 +193,36 @@
|
||||
"gmmk/pro/iso": {
|
||||
"target": "gmmk/pro/rev1/iso"
|
||||
},
|
||||
"handwired/dactyl_manuform/3x5_3": {
|
||||
"target": "handwired/dactyl_minidox"
|
||||
},
|
||||
"handwired/dactyl_manuform/6x6_kinesis": {
|
||||
"target": "handwired/dactyl_kinesis"
|
||||
},
|
||||
"handwired/ferris": {
|
||||
"target": "ferris/0_1"
|
||||
},
|
||||
"handwired/ibm122m": {
|
||||
"target": "ibm/model_m_122/ibm122m"
|
||||
},
|
||||
"handwired/p1800fl": {
|
||||
"target": "team0110/p1800fl"
|
||||
},
|
||||
"handwired/jscotto/scotto9": {
|
||||
"target": "handwired/scottokeebs/scotto9"
|
||||
},
|
||||
"handwired/jscotto/scotto36": {
|
||||
"target": "handwired/scottokeebs/scotto36"
|
||||
},
|
||||
"handwired/jscotto/scotto40": {
|
||||
"target": "handwired/scottokeebs/scotto40"
|
||||
},
|
||||
"handwired/jscotto/scottocmd": {
|
||||
"target": "handwired/scottokeebs/scottocmd"
|
||||
},
|
||||
"handwired/jscotto/scottostarter": {
|
||||
"target": "handwired/scottokeebs/scottostarter"
|
||||
},
|
||||
"helix/pico/sc/back": {
|
||||
"target": "helix/pico/sc"
|
||||
},
|
||||
@ -240,14 +266,14 @@
|
||||
"target": "keyhive/honeycomb"
|
||||
},
|
||||
"idb_60": {
|
||||
"target": "idb/idb_60",
|
||||
"layouts": {
|
||||
"LAYOUT": "LAYOUT_all"
|
||||
}
|
||||
"target": "idb/idb_60"
|
||||
},
|
||||
"idobo": {
|
||||
"target": "idobao/id75"
|
||||
},
|
||||
"jacky_studio/piggy60": {
|
||||
"target": "jacky_studio/piggy60/rev1"
|
||||
},
|
||||
"jj40": {
|
||||
"target": "kprepublic/jj40"
|
||||
},
|
||||
@ -260,18 +286,21 @@
|
||||
"jones": {
|
||||
"target": "jones/v03_1"
|
||||
},
|
||||
"kamigakushi": {
|
||||
"target": "jaykeeb/kamigakushi"
|
||||
},
|
||||
"katana60": {
|
||||
"target": "rominronin/katana60/rev1"
|
||||
},
|
||||
"kbdfans/kbd67mkiirgb": {
|
||||
"target": "kbdfans/kbd67/mkiirgb",
|
||||
"layouts": {
|
||||
"LAYOUT": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
"target": "kbdfans/kbd67/mkiirgb"
|
||||
},
|
||||
"kbdfans/kbd67/mkiirgb": {
|
||||
"target": "kbdfans/kbd67/mkiirgb/v1"
|
||||
},
|
||||
"keebio/chocopad": {
|
||||
"target": "keebio/chocopad/rev1"
|
||||
},
|
||||
"keebio/dsp40": {
|
||||
"target": "keebio/dsp40/rev1"
|
||||
},
|
||||
@ -407,10 +436,8 @@
|
||||
"montsinger/rebound": {
|
||||
"target": "montsinger/rebound/rev1"
|
||||
},
|
||||
"noxary/268_2": {
|
||||
"layouts": {
|
||||
"LAYOUT": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
"mschwingen/modelm": {
|
||||
"target": "ibm/model_m/mschwingen"
|
||||
},
|
||||
"oddball": {
|
||||
"target": "oddball/v1"
|
||||
@ -436,11 +463,6 @@
|
||||
"peiorisboards/ixora": {
|
||||
"target": "coarse/ixora"
|
||||
},
|
||||
"percent/canoe": {
|
||||
"layouts": {
|
||||
"LAYOUT_iso": "LAYOUT_65_iso_blocker"
|
||||
}
|
||||
},
|
||||
"plaid": {
|
||||
"target": "dm9records/plaid"
|
||||
},
|
||||
@ -453,21 +475,6 @@
|
||||
"polilla": {
|
||||
"target": "polilla/rev1"
|
||||
},
|
||||
"preonic/rev1": {
|
||||
"layouts": {
|
||||
"LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
|
||||
}
|
||||
},
|
||||
"preonic/rev2": {
|
||||
"layouts": {
|
||||
"LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
|
||||
}
|
||||
},
|
||||
"preonic/rev3": {
|
||||
"layouts": {
|
||||
"LAYOUT_preonic_grid": "LAYOUT_ortho_5x12"
|
||||
}
|
||||
},
|
||||
"primekb/prime_l": {
|
||||
"target": "primekb/prime_l/v1"
|
||||
},
|
||||
@ -559,10 +566,7 @@
|
||||
"target": "underscore33/rev1"
|
||||
},
|
||||
"vinta": {
|
||||
"target": "coarse/vinta",
|
||||
"layouts": {
|
||||
"LAYOUT_67_ansi": "LAYOUT_65_ansi_blocker"
|
||||
}
|
||||
"target": "coarse/vinta"
|
||||
},
|
||||
"wasdat": {
|
||||
"target": "maartenwut/wasdat"
|
||||
@ -832,6 +836,9 @@
|
||||
"hecomi/alpha": {
|
||||
"target": "takashiski/hecomi/alpha"
|
||||
},
|
||||
"hfdkb/keyboard_sw/k83":{
|
||||
"target": "inland/kb83"
|
||||
},
|
||||
"hid_liber": {
|
||||
"target": "bpiphany/hid_liber"
|
||||
},
|
||||
@ -925,6 +932,12 @@
|
||||
"m3n3van": {
|
||||
"target": "matthewdias/m3n3van"
|
||||
},
|
||||
"massdrop/thekey": {
|
||||
"target": "drop/thekey/v1"
|
||||
},
|
||||
"massdrop/thekey_v2": {
|
||||
"target": "drop/thekey/v2"
|
||||
},
|
||||
"mechmini/v1": {
|
||||
"target": "mechkeys/mechmini/v1"
|
||||
},
|
||||
@ -1222,6 +1235,9 @@
|
||||
"treadstone48/rev2": {
|
||||
"target": "marksard/treadstone48/rev2"
|
||||
},
|
||||
"tronguylabs/m122_3270": {
|
||||
"target": "ibm/model_m_122/m122_3270"
|
||||
},
|
||||
"ua62": {
|
||||
"target": "nacly/ua62"
|
||||
},
|
||||
@ -1282,6 +1298,9 @@
|
||||
"ymdk_np21": {
|
||||
"target": "ymdk/np21"
|
||||
},
|
||||
"yugo_m/model_m_101": {
|
||||
"target": "ibm/model_m/yugo_m"
|
||||
},
|
||||
"yurei": {
|
||||
"target": "kkatano/yurei"
|
||||
},
|
||||
|
@ -29,6 +29,10 @@
|
||||
"minLength": 1,
|
||||
"maxLength": 250
|
||||
},
|
||||
"snake_case": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_]*$"
|
||||
},
|
||||
"layout_macro": {
|
||||
"oneOf": [
|
||||
{
|
||||
@ -71,6 +75,38 @@
|
||||
"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"}
|
||||
|
@ -35,7 +35,7 @@
|
||||
},
|
||||
"development_board": {
|
||||
"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"]
|
||||
"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"]
|
||||
},
|
||||
"pin_compatible": {
|
||||
"type": "string",
|
||||
@ -71,6 +71,8 @@
|
||||
"STM32F446",
|
||||
"STM32G431",
|
||||
"STM32G474",
|
||||
"STM32H723",
|
||||
"STM32H733",
|
||||
"STM32L412",
|
||||
"STM32L422",
|
||||
"STM32L432",
|
||||
@ -96,6 +98,19 @@
|
||||
"unknown"
|
||||
]
|
||||
},
|
||||
"apa102": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"data_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"clock_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"default_brightness": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 31
|
||||
}
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@ -133,7 +148,7 @@
|
||||
"properties": {
|
||||
"driver": {
|
||||
"type": "string",
|
||||
"enum": ["BluefruitLE", "RN42"]
|
||||
"enum": ["bluefruit_le", "custom", "rn42"]
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -161,6 +176,7 @@
|
||||
"bootloader": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"apm32-dfu",
|
||||
"atmel-dfu",
|
||||
"bootloadhid",
|
||||
"caterina",
|
||||
@ -214,7 +230,8 @@
|
||||
"enabled": {"type": "boolean"},
|
||||
"both_shifts_turns_on": {"type": "boolean"},
|
||||
"double_tap_shift_turns_on": {"type": "boolean"},
|
||||
"idle_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
"idle_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"invert_on_shift": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"combo": {
|
||||
@ -228,13 +245,22 @@
|
||||
"type": "array",
|
||||
"items": {"$ref": "qmk.definitions.v1#/filename"}
|
||||
},
|
||||
"eeprom": {
|
||||
"properties": {
|
||||
"driver": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"encoder": {
|
||||
"$ref": "#/definitions/encoder_config",
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"features": {"$ref": "qmk.definitions.v1#/boolean_array"},
|
||||
"features": {
|
||||
"$ref": "qmk.definitions.v1#/boolean_array",
|
||||
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
|
||||
|
||||
},
|
||||
"indicators": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -246,6 +272,7 @@
|
||||
"on_state": {"$ref": "qmk.definitions.v1#/bit"}
|
||||
}
|
||||
},
|
||||
"keycodes": {"$ref": "qmk.definitions.v1#/keycode_decl_array"},
|
||||
"layout_aliases": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"$ref": "qmk.definitions.v1#/layout_macro"}
|
||||
@ -347,6 +374,7 @@
|
||||
"properties": {
|
||||
"animations": {
|
||||
"type": "object",
|
||||
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
@ -360,8 +388,6 @@
|
||||
},
|
||||
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"sat_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"val_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"speed_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"split_count": {
|
||||
@ -398,6 +424,7 @@
|
||||
"properties": {
|
||||
"animations": {
|
||||
"type": "object",
|
||||
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
@ -450,11 +477,16 @@
|
||||
"properties": {
|
||||
"animations": {
|
||||
"type": "object",
|
||||
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"driver": {
|
||||
"type": "string",
|
||||
"enum": ["apa102", "custom", "ws2812"]
|
||||
},
|
||||
"hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"layers": {
|
||||
"type": "object",
|
||||
@ -471,8 +503,16 @@
|
||||
}
|
||||
},
|
||||
"led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"led_map": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
},
|
||||
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"pin": {
|
||||
"$ref": "qmk.definitions.v1#/mcu_pin",
|
||||
"$comment": "Deprecated: use ws2812.pin instead"
|
||||
},
|
||||
"rgbw": {"type": "boolean"},
|
||||
"saturation_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"sleep": {"type": "boolean"},
|
||||
@ -686,6 +726,19 @@
|
||||
"led": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"speaker": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
}
|
||||
},
|
||||
"ws2812": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"driver": {
|
||||
"type": "string",
|
||||
"enum": ["bitbang", "custom", "i2c", "pwm", "spi", "vendor"]
|
||||
},
|
||||
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"i2c_address": {"$ref": "qmk.definitions.v1#/hex_number_2d"},
|
||||
"i2c_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,7 @@
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 50,
|
||||
"pattern": "^[A-Zs_0-9]*$"
|
||||
},
|
||||
"hex_number_4d": {
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9A-F]{4}$"
|
||||
"pattern": "^[A-Z][A-Zs_0-9]*$"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
@ -34,10 +30,10 @@
|
||||
"keycodes": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/definitions/hex_number_4d"
|
||||
"$ref": "qmk.definitions.v1#/hex_number_4d"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"type": "object", // use 'qmk.definitions.v1#/keycode_decl' when problem keycodes are removed
|
||||
"required": [
|
||||
"key"
|
||||
],
|
||||
|
@ -67,6 +67,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"keycodes": {"$ref": "qmk.definitions.v1#/keycode_decl_array"},
|
||||
"config": {"$ref": "qmk.keyboard.v1"},
|
||||
"notes": {
|
||||
"type": "string"
|
||||
|
551
docs/ChangeLog/20230528.md
Normal file
551
docs/ChangeLog/20230528.md
Normal file
@ -0,0 +1,551 @@
|
||||
# QMK Breaking Changes - 2023 May 28 Changelog
|
||||
|
||||
## Notable Changes :id=notable-changes
|
||||
|
||||
As per last breaking changes cycle, there has been _a lot_ of emphasis on 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.
|
||||
|
||||
Of note for keyboard designers:
|
||||
|
||||
* Layout and matrix definitions in `info.json` are now _mandatory_ for merge into QMK.
|
||||
* Layout macros in `<yourkeyboard>.h` are no longer accepted into QMK Firmware.
|
||||
* Existing keyboards have been meticulously converted by the QMK collaborators
|
||||
* Layouts missing from keyboard definitions have been added in the process
|
||||
* Keys within layouts should not specify `"w":1` or `"h":1` if the key size is 1 -- `w`/`h` should only be present for sizes other than 1
|
||||
* `config_common.h` has been removed and should not be present anywhere in your keyboard code.
|
||||
* `RGB_DI_PIN` will now cause an error during build:
|
||||
* For WS2812-like LEDs, this should be moved to `info.json`: `"ws2812": { "pin": "xxx" }`
|
||||
* For APA102 LEDs, this should be moved to `info.json`: `"apa102": { "data_pin": "xxx" }`
|
||||
* Other mandatory data-driven changes should be automatically flagged during build
|
||||
* Keymaps with `encoder_map` should now have the following change made:
|
||||
* `encoder_map[][NUM_ENCODERS][2]` => `encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS]`
|
||||
* Users assumed the `2` referred to the number of encoders, rather than the number of directions (which is always 2)
|
||||
|
||||
### Repeat last key ([#19700](https://github.com/qmk/qmk_firmware/pull/19700)) :id=repeat-last-key
|
||||
|
||||
A new pair of keys has been added to QMK -- namely `QK_REPEAT_KEY` and `QK_ALT_REPEAT_KEY` (shortened: `QK_REP`/`QK_AREP`). These allow you to repeat the last key pressed, or in the case of the alternate key, press the "opposite" of the last key. For example, if you press `KC_LEFT`, pressing `QK_REPEAT_KEY` afterwards repeats `KC_LEFT`, but pressing `QK_ALT_REPEAT_KEY` instead sends `KC_RIGHT`.
|
||||
|
||||
The full list of default alternate keys is available on the [Repeat Key](feature_repeat_key.md) documentation.
|
||||
|
||||
To enable these keys, in your keymap's `rules.mk`, add:
|
||||
|
||||
```make
|
||||
REPEAT_KEY_ENABLE = yes
|
||||
```
|
||||
|
||||
...and add them to your keymap.
|
||||
|
||||
### User callback for pre process record ([#20584](https://github.com/qmk/qmk_firmware/pull/20584)) :id=user-callback-for-pre-process-record
|
||||
|
||||
Two new boolean callback functions, `pre_process_record_kb` and `pre_process_record_user`, have been added. They are called at the beginning of `process_record`, right before `process_combo`.
|
||||
|
||||
Similar to existing `*_kb` and `*_user` callback functions, returning `false` will halt further processing of key events. The `pre_process_record_user` function will allow user space opportunity to handle or capture an input before it undergoes quantum processing. For example, while action tapping is still resolving the tap or hold output of a mod-tap key, `pre_process_record_user` can capture the next key record of an input event that follows. That key record can be used to influence the [decision of the mod-tap](https://docs.qmk.fm/#/tap_hold) key that is currently undergoing quantum processing.
|
||||
|
||||
### Consolidate modelm ([#14996](https://github.com/qmk/qmk_firmware/pull/14996) :id=consolidate-modelm
|
||||
|
||||
Several build targets for the IBM Model M were cluttered in different folders. The maintainers of several Model M replacement controller projects agreed to consolidate them under one common folder.
|
||||
|
||||
The list of all moved keyboard locations is listed [below](20230528.md#updated-keyboard-codebases).
|
||||
|
||||
## Changes Requiring User Action :id=changes-requiring-user-action
|
||||
|
||||
### `IGNORE_MOD_TAP_INTERRUPT` behaviour changes ([#20211](https://github.com/qmk/qmk_firmware/pull/20211)) :id=i-m-t-i
|
||||
|
||||
Following up from the last breaking changes cycle, `IGNORE_MOD_TAP_INTERRUPT` has been removed and if present in keymap code, will now fail to build. The previous functionality for `IGNORE_MOD_TAP_INTERRUPT` is now default, and should you wish to revert to the old behaviour, you can use `HOLD_ON_OTHER_KEY_PRESS` instead.
|
||||
|
||||
For more information, you are invited to read the section on [HOLD_ON_OTHER_KEY_PRESS](tap_hold.md#hold-on-other-key-press) in the page on [Tap-Hold configuration options](tap_hold.md).
|
||||
|
||||
### Updated Keyboard Codebases :id=updated-keyboard-codebases
|
||||
|
||||
| Old Keyboard Name | New Keyboard Name |
|
||||
|---------------------------------|-------------------------------------|
|
||||
| ashpil/modelm_usbc | ibm/model_m/ashpil_usbc |
|
||||
| binepad/bn009r2 | binepad/bn009/r2 |
|
||||
| converter/modelm101 | ibm/model_m/teensypp |
|
||||
| converter/modelm101_teensy2 | ibm/model_m/teensy2 |
|
||||
| converter/modelm_ssk | ibm/model_m_ssk/teensypp_ssk |
|
||||
| durgod/dgk6x/hades | durgod/dgk6x/hades_ansi |
|
||||
| handwired/ibm122m | ibm/model_m_122/ibm122m |
|
||||
| jacky_studio/piggy60/hotswap | jacky_studio/piggy60/rev1/hotswap |
|
||||
| jacky_studio/piggy60/solder | jacky_studio/piggy60/rev1/solder |
|
||||
| kamigakushi | jaykeeb/kamigakushi |
|
||||
| massdrop/thekey | drop/thekey/v1 |
|
||||
| massdrop/thekey_v2 | drop/thekey/v2 |
|
||||
| mschwingen/modelm | ibm/model_m/mschwingen |
|
||||
| tronguylabs/m122_3270 | ibm/model_m_122/m122_3270 |
|
||||
| tronguylabs/m122_3270/blackpill | ibm/model_m_122/m122_3270/blackpill |
|
||||
| tronguylabs/m122_3270/bluepill | ibm/model_m_122/m122_3270/bluepill |
|
||||
| tronguylabs/m122_3270/teensy | ibm/model_m_122/m122_3270/teensy |
|
||||
| yugo_m/model_m_101 | ibm/model_m/yugo_m |
|
||||
|
||||
## Notable core changes :id=notable-core
|
||||
|
||||
### Encoder functionality fallback ([#20320](https://github.com/qmk/qmk_firmware/pull/20320)) :id=encoder-functionality-fallback
|
||||
|
||||
For keyboards who have not yet been migrated to encoder map, a default set of encoder functionality is now enabled, gracefully degrading functionality depending on which flags are enabled by the keyboard:
|
||||
|
||||
* If `EXTRAKEY_ENABLE` is enabled by the keyboard, the encoder will be mapped to `KC_VOLU`/`KC_VOLD`
|
||||
* If `MOUSEKEY_ENABLE` is enabled by the keyboard, the encoder will be mapped to `KC_MS_WH_UP`/`KC_MS_WH_DOWN`
|
||||
* Otherwise, `KC_PGDN`/`KC_PGUP` will be used
|
||||
|
||||
Additionally, this ensures that builds on QMK Configurator produce some sort of usable encoder mapping.
|
||||
|
||||
### OLED Driver Improvements ([#20331](https://github.com/qmk/qmk_firmware/pull/20331)) :id=oled-driver-improvements
|
||||
|
||||
The "classic" OLED driver picked up support for additional sizes of OLED displays, support for the SH1107 controller, and SPI-based OLED support.
|
||||
|
||||
Other configurable items are available and can be found on the [OLED Driver page](https://docs.qmk.fm/#/feature_oled_driver).
|
||||
|
||||
## Full changelist :id=full-changelist
|
||||
|
||||
Core:
|
||||
* Refactor `keyevent_t` for 1ms timing resolution ([#15847](https://github.com/qmk/qmk_firmware/pull/15847))
|
||||
* PS/2 PIO Driver for RP2040 ([#17893](https://github.com/qmk/qmk_firmware/pull/17893))
|
||||
* Relocate various modifier defines ([#18638](https://github.com/qmk/qmk_firmware/pull/18638))
|
||||
* Added PMW3320 driver ([#19543](https://github.com/qmk/qmk_firmware/pull/19543))
|
||||
* Keymap introspection for combos. ([#19670](https://github.com/qmk/qmk_firmware/pull/19670))
|
||||
* Add direction to dynamic_macro_record_start_user ([#19689](https://github.com/qmk/qmk_firmware/pull/19689))
|
||||
* Add Repeat Key ("repeat last key") as a core feature. ([#19700](https://github.com/qmk/qmk_firmware/pull/19700))
|
||||
* [Cleanup] Quantum Painter ([#19825](https://github.com/qmk/qmk_firmware/pull/19825))
|
||||
* Improve robustness of AW20216 driver ([#19849](https://github.com/qmk/qmk_firmware/pull/19849))
|
||||
* Make "detected_host_os()" available on the SLAVE side of the split keyboard ([#19854](https://github.com/qmk/qmk_firmware/pull/19854))
|
||||
* Add RP2040 Community Edition alias for splitkb.com's Liatris controller ([#19966](https://github.com/qmk/qmk_firmware/pull/19966))
|
||||
* Remove some use of keymap.h ([#19980](https://github.com/qmk/qmk_firmware/pull/19980))
|
||||
* Merge upstream changes to uf2conv ([#19993](https://github.com/qmk/qmk_firmware/pull/19993))
|
||||
* Remove keymap.h ([#20004](https://github.com/qmk/qmk_firmware/pull/20004))
|
||||
* Remove some use of keymap.h ([#20006](https://github.com/qmk/qmk_firmware/pull/20006))
|
||||
* Quantum Painter QoL enhancements -- auto-poweroff, auto-flush, buffer sizing ([#20013](https://github.com/qmk/qmk_firmware/pull/20013))
|
||||
* Make Pointing Device Auto Layer more configurable ([#20061](https://github.com/qmk/qmk_firmware/pull/20061))
|
||||
* Add last activity functions for pointing device ([#20079](https://github.com/qmk/qmk_firmware/pull/20079))
|
||||
* Caps Word "Invert on shift" option: pressing Shift inverts the shift state. ([#20092](https://github.com/qmk/qmk_firmware/pull/20092))
|
||||
* Remove bootloader logic from `mcu_selection.mk` ([#20150](https://github.com/qmk/qmk_firmware/pull/20150))
|
||||
* Update qmk_cli container references ([#20154](https://github.com/qmk/qmk_firmware/pull/20154))
|
||||
* Clean up APA102 config and add DD mapping ([#20159](https://github.com/qmk/qmk_firmware/pull/20159))
|
||||
* Sync activity timestamps between sides. ([#20192](https://github.com/qmk/qmk_firmware/pull/20192))
|
||||
* Update Doxygen comments for some headers ([#20194](https://github.com/qmk/qmk_firmware/pull/20194))
|
||||
* Make IGNORE_MOD_TAP_INTERRUPT the default behaviour for mod-taps ([#20211](https://github.com/qmk/qmk_firmware/pull/20211))
|
||||
* Add some helpers to tidy up XAP ([#20235](https://github.com/qmk/qmk_firmware/pull/20235))
|
||||
* Tidy up duplication of MIN/MAX fallback implementations ([#20236](https://github.com/qmk/qmk_firmware/pull/20236))
|
||||
* Optionally keep intermediate file listings in order to do comparisons between builds. ([#20237](https://github.com/qmk/qmk_firmware/pull/20237))
|
||||
* Add basic profiler. ([#20238](https://github.com/qmk/qmk_firmware/pull/20238))
|
||||
* WS2812 driver improvements ([#20262](https://github.com/qmk/qmk_firmware/pull/20262))
|
||||
* typing_heatmap: Add macro to configure increase steps ([#20300](https://github.com/qmk/qmk_firmware/pull/20300))
|
||||
* Migrate `rgblight.pin` and `RGB_DI_PIN` to `ws2812.pin` ([#20303](https://github.com/qmk/qmk_firmware/pull/20303))
|
||||
* Delete config_common.h ([#20312](https://github.com/qmk/qmk_firmware/pull/20312))
|
||||
* Allow EEPROM_DRIVER from info.json ([#20313](https://github.com/qmk/qmk_firmware/pull/20313))
|
||||
* rp2040: *_PAL_MODE overridable for this platform too ([#20314](https://github.com/qmk/qmk_firmware/pull/20314))
|
||||
* Add core/fallback encoder behaviour ([#20320](https://github.com/qmk/qmk_firmware/pull/20320))
|
||||
* OLED Driver improvements ([#20331](https://github.com/qmk/qmk_firmware/pull/20331))
|
||||
* [Chore] Remove stray mod tap interrupt defines and per key functions ([#20347](https://github.com/qmk/qmk_firmware/pull/20347))
|
||||
* Add swap hands toggle functions ([#20381](https://github.com/qmk/qmk_firmware/pull/20381))
|
||||
* Prevent Tri-Layer keys from stopping caps word ([#20398](https://github.com/qmk/qmk_firmware/pull/20398))
|
||||
* quantum/action_util.c: Use uint8_t for oneshot_layer_data ([#20423](https://github.com/qmk/qmk_firmware/pull/20423))
|
||||
* Encoder map direction define. ([#20454](https://github.com/qmk/qmk_firmware/pull/20454))
|
||||
* Realign and size check EECONFIG structures ([#20541](https://github.com/qmk/qmk_firmware/pull/20541))
|
||||
* Clean up ISSI drivers, Add IS31FL3736 support ([#20572](https://github.com/qmk/qmk_firmware/pull/20572))
|
||||
* Add a user callback for pre process record ([#20584](https://github.com/qmk/qmk_firmware/pull/20584))
|
||||
* Disable debug on QP's internal task ([#20623](https://github.com/qmk/qmk_firmware/pull/20623))
|
||||
* Add required string header file ([#20638](https://github.com/qmk/qmk_firmware/pull/20638))
|
||||
* Add Develop is31fl3736 multi drivers ([#20642](https://github.com/qmk/qmk_firmware/pull/20642))
|
||||
* Support PS/2 mouse 9-bit output with MOUSE_EXTENDED_REPORT ([#20734](https://github.com/qmk/qmk_firmware/pull/20734))
|
||||
* BIOI G60/Morgan65: use custom Bluetooth driver ([#20897](https://github.com/qmk/qmk_firmware/pull/20897))
|
||||
* Move `pre_process_record_kb()` before `process_combo()` ([#20969](https://github.com/qmk/qmk_firmware/pull/20969))
|
||||
* Implement UF2 device type id extension tag ([#21029](https://github.com/qmk/qmk_firmware/pull/21029))
|
||||
|
||||
CLI:
|
||||
* Add force support to 'qmk git-submodule' ([#19705](https://github.com/qmk/qmk_firmware/pull/19705))
|
||||
* JSON encoder: improve sorting of layout dict keys ([#19974](https://github.com/qmk/qmk_firmware/pull/19974))
|
||||
* Increase verbosity of make command ([#20172](https://github.com/qmk/qmk_firmware/pull/20172))
|
||||
* Append user variables to the end of make command ([#20177](https://github.com/qmk/qmk_firmware/pull/20177))
|
||||
* Strip API specific output from `qmk info` ([#20234](https://github.com/qmk/qmk_firmware/pull/20234))
|
||||
* `qmk find`: usability improvements ([#20440](https://github.com/qmk/qmk_firmware/pull/20440))
|
||||
* `qmk format-json`: Expose full key path and respect `sort_keys` ([#20836](https://github.com/qmk/qmk_firmware/pull/20836))
|
||||
* Update json2c to use dump_lines ([#21013](https://github.com/qmk/qmk_firmware/pull/21013))
|
||||
|
||||
Submodule updates:
|
||||
* Update ChibiOS to latest stable 21.11.x ([#20470](https://github.com/qmk/qmk_firmware/pull/20470))
|
||||
|
||||
Keyboards:
|
||||
* Allow a larger int for the idle timeout for urbanvanilla keymap ([#19738](https://github.com/qmk/qmk_firmware/pull/19738))
|
||||
* Change aidansmithdotdev/fine40 to use Encoder Map ([#19912](https://github.com/qmk/qmk_firmware/pull/19912))
|
||||
* Custom keycodes in JSON ([#19925](https://github.com/qmk/qmk_firmware/pull/19925))
|
||||
* Remove `"w":1` and `"h":1` from info.json ([#19961](https://github.com/qmk/qmk_firmware/pull/19961))
|
||||
* Move matrix config to info.json, part 1 ([#19985](https://github.com/qmk/qmk_firmware/pull/19985))
|
||||
* Move matrix config to info.json, part 2 ([#19987](https://github.com/qmk/qmk_firmware/pull/19987))
|
||||
* Move matrix config to info.json, part 3 ([#19991](https://github.com/qmk/qmk_firmware/pull/19991))
|
||||
* Move matrix config to info.json, part 4 ([#20001](https://github.com/qmk/qmk_firmware/pull/20001))
|
||||
* Move matrix config to info.json, part 5 ([#20003](https://github.com/qmk/qmk_firmware/pull/20003))
|
||||
* Move matrix config to info.json, part 6 ([#20019](https://github.com/qmk/qmk_firmware/pull/20019))
|
||||
* Move matrix config to info.json, part 7 ([#20020](https://github.com/qmk/qmk_firmware/pull/20020))
|
||||
* Move matrix config to info.json, part 8 ([#20030](https://github.com/qmk/qmk_firmware/pull/20030))
|
||||
* Remove empty rules.mk from keymaps ([#20056](https://github.com/qmk/qmk_firmware/pull/20056))
|
||||
* Adjust offset for some layouts ([#20075](https://github.com/qmk/qmk_firmware/pull/20075))
|
||||
* Remove useless "ifdef KEYBOARD_*" ([#20078](https://github.com/qmk/qmk_firmware/pull/20078))
|
||||
* Remove pointless `USE_I2C` blocks in keyboard headers ([#20084](https://github.com/qmk/qmk_firmware/pull/20084))
|
||||
* Add support for ISO version of Durgod Hades ([#20110](https://github.com/qmk/qmk_firmware/pull/20110))
|
||||
* Consolidate Binepad BN009 R1 and R2 into common folder ([#20113](https://github.com/qmk/qmk_firmware/pull/20113))
|
||||
* Remove more empty headers ([#20155](https://github.com/qmk/qmk_firmware/pull/20155))
|
||||
* Remove trailing zeroes in info.json layouts ([#20156](https://github.com/qmk/qmk_firmware/pull/20156))
|
||||
* Clean up usage of `QMK_KEYBOARD_H` ([#20167](https://github.com/qmk/qmk_firmware/pull/20167))
|
||||
* Move Keychron Q0 and Q0 Plus data-driven configuration; `keychron` keymap `rules.mk` cleanup ([#20168](https://github.com/qmk/qmk_firmware/pull/20168))
|
||||
* Move ortho & numpad layouts to data driven ([#20183](https://github.com/qmk/qmk_firmware/pull/20183))
|
||||
* Remove `RGB_DI_PIN` ifdefs ([#20218](https://github.com/qmk/qmk_firmware/pull/20218))
|
||||
* Add the KJ-Modify RS40 PCB keyboard ([#20243](https://github.com/qmk/qmk_firmware/pull/20243))
|
||||
* Move `WS2812_DRIVER` to data driven ([#20248](https://github.com/qmk/qmk_firmware/pull/20248))
|
||||
* [jacky_studio/piggy60] move AVR PCB under rev1 ([#20253](https://github.com/qmk/qmk_firmware/pull/20253))
|
||||
* Move 75% and 96% layouts to data driven ([#20289](https://github.com/qmk/qmk_firmware/pull/20289))
|
||||
* Move split layouts to data driven ([#20290](https://github.com/qmk/qmk_firmware/pull/20290))
|
||||
* Move 66% and 68% layouts to data driven ([#20293](https://github.com/qmk/qmk_firmware/pull/20293))
|
||||
* add jacky_studio/piggy60/rev2 ([#20297](https://github.com/qmk/qmk_firmware/pull/20297))
|
||||
* Move 65% layouts to data driven ([#20308](https://github.com/qmk/qmk_firmware/pull/20308))
|
||||
* Move TKL F13 and FRL layouts to data driven ([#20310](https://github.com/qmk/qmk_firmware/pull/20310))
|
||||
* Remove some use of keymap.h ([#20316](https://github.com/qmk/qmk_firmware/pull/20316))
|
||||
* Move fullsize layouts to data driven ([#20317](https://github.com/qmk/qmk_firmware/pull/20317))
|
||||
* Add 36-key layout for Beekeeb Piantor ([#20328](https://github.com/qmk/qmk_firmware/pull/20328))
|
||||
* Add sriwedari70 and move kamigakushi to new folder ([#20334](https://github.com/qmk/qmk_firmware/pull/20334))
|
||||
* Move TKL layouts to data driven ([#20337](https://github.com/qmk/qmk_firmware/pull/20337))
|
||||
* Move Alice and Ergodox layouts to data driven ([#20340](https://github.com/qmk/qmk_firmware/pull/20340))
|
||||
* Move small macropad-ish layouts to data driven ([#20341](https://github.com/qmk/qmk_firmware/pull/20341))
|
||||
* Move `default` layouts to data driven ([#20349](https://github.com/qmk/qmk_firmware/pull/20349))
|
||||
* Move `RGB_MATRIX_DRIVER` to data driven ([#20350](https://github.com/qmk/qmk_firmware/pull/20350))
|
||||
* Move split space/backspace layouts to data driven ([#20356](https://github.com/qmk/qmk_firmware/pull/20356))
|
||||
* Move single `LAYOUT`s to data driven ([#20365](https://github.com/qmk/qmk_firmware/pull/20365))
|
||||
* Add encoder map for Iris Rev. 5 VIA ([#20412](https://github.com/qmk/qmk_firmware/pull/20412))
|
||||
* Move remaining `LAYOUT`s to data driven ([#20422](https://github.com/qmk/qmk_firmware/pull/20422))
|
||||
* Move single `LAYOUT_all`s to data driven ([#20430](https://github.com/qmk/qmk_firmware/pull/20430))
|
||||
* 4pplet/yakiimo Layout Macro Conversion and Additions ([#20436](https://github.com/qmk/qmk_firmware/pull/20436))
|
||||
* Move single `60_ansi`, `60_hhkb` and `60_iso` layouts to data driven ([#20438](https://github.com/qmk/qmk_firmware/pull/20438))
|
||||
* Update brauner preonic layout ([#20439](https://github.com/qmk/qmk_firmware/pull/20439))
|
||||
* AEBoards Satellite Rev1 Layout Macro Conversion ([#20442](https://github.com/qmk/qmk_firmware/pull/20442))
|
||||
* Acheron Austin Layout Macro Conversion and Additions ([#20443](https://github.com/qmk/qmk_firmware/pull/20443))
|
||||
* Move remaining `LAYOUT_all`s to data driven ([#20463](https://github.com/qmk/qmk_firmware/pull/20463))
|
||||
* Update lotus58 RGB config ([#20468](https://github.com/qmk/qmk_firmware/pull/20468))
|
||||
* Cleanup `ekow/akira` ([#20474](https://github.com/qmk/qmk_firmware/pull/20474))
|
||||
* Move 60% layouts to data driven ([#20477](https://github.com/qmk/qmk_firmware/pull/20477))
|
||||
* Move DZ60 and MJ6XY layouts to data driven ([#20478](https://github.com/qmk/qmk_firmware/pull/20478))
|
||||
* AEBoards Constellation Layout Macro Updates ([#20487](https://github.com/qmk/qmk_firmware/pull/20487))
|
||||
* AI03 Equinox Layout Macro Additions ([#20488](https://github.com/qmk/qmk_firmware/pull/20488))
|
||||
* AI03 Vega Layout Macro Additions ([#20489](https://github.com/qmk/qmk_firmware/pull/20489))
|
||||
* AKB OGR Layout Macro Additions ([#20490](https://github.com/qmk/qmk_firmware/pull/20490))
|
||||
* AKB Vero Layout Macro Additions ([#20491](https://github.com/qmk/qmk_firmware/pull/20491))
|
||||
* Alf DC60 Layout Macro Additions ([#20494](https://github.com/qmk/qmk_firmware/pull/20494))
|
||||
* Alf X2 Layout Macro Additions ([#20495](https://github.com/qmk/qmk_firmware/pull/20495))
|
||||
* Koolertron AMAG23 Touch-Up ([#20496](https://github.com/qmk/qmk_firmware/pull/20496))
|
||||
* BIOI G60 Layout Macro Additions ([#20498](https://github.com/qmk/qmk_firmware/pull/20498))
|
||||
* BIOI Morgan65 Layout Macro Additions ([#20499](https://github.com/qmk/qmk_firmware/pull/20499))
|
||||
* BIOI S65 Layout Macro Additions ([#20500](https://github.com/qmk/qmk_firmware/pull/20500))
|
||||
* Boston Layout Macro Additions ([#20504](https://github.com/qmk/qmk_firmware/pull/20504))
|
||||
* Potato65S Layout Macro Additions ([#20508](https://github.com/qmk/qmk_firmware/pull/20508))
|
||||
* Move miscellaneous layouts to data driven ([#20516](https://github.com/qmk/qmk_firmware/pull/20516))
|
||||
* Cable Car Designs Cypher rev6 Layout Additions and Touch-Up ([#20518](https://github.com/qmk/qmk_firmware/pull/20518))
|
||||
* Caffeinated Studios Serpent65 Layout Macro Additions ([#20519](https://github.com/qmk/qmk_firmware/pull/20519))
|
||||
* CannonKeys Adelie Layout Macro Additions ([#20546](https://github.com/qmk/qmk_firmware/pull/20546))
|
||||
* CannonKeys Aella Layout Macro Additions ([#20547](https://github.com/qmk/qmk_firmware/pull/20547))
|
||||
* CannonKeys Balance Layout Macro Additions and Touch-Up ([#20548](https://github.com/qmk/qmk_firmware/pull/20548))
|
||||
* CannonKeys Brutal v2 1800 Layout Macro Additions ([#20549](https://github.com/qmk/qmk_firmware/pull/20549))
|
||||
* CannonKeys Brutal v2 65 Layout Macro Additions ([#20552](https://github.com/qmk/qmk_firmware/pull/20552))
|
||||
* CannonKeys Cloudline Layout Macro Additions ([#20553](https://github.com/qmk/qmk_firmware/pull/20553))
|
||||
* CannonKeys Crin Layout Macro Additions ([#20554](https://github.com/qmk/qmk_firmware/pull/20554))
|
||||
* CannonKeys DevastatingTKL Layout Macro Additions ([#20555](https://github.com/qmk/qmk_firmware/pull/20555))
|
||||
* CannonKeys Ellipse Layout Macro Additions ([#20558](https://github.com/qmk/qmk_firmware/pull/20558))
|
||||
* CannonKeys Ellipse Hotswap Layout Macro Addition & Touch-Up ([#20560](https://github.com/qmk/qmk_firmware/pull/20560))
|
||||
* CannonKeys Gentoo Layout Macro Additions ([#20561](https://github.com/qmk/qmk_firmware/pull/20561))
|
||||
* CannonKeys Gentoo Hotswap Touch-Up ([#20562](https://github.com/qmk/qmk_firmware/pull/20562))
|
||||
* CannonKeys HoodrowG Layout Macro Additions ([#20563](https://github.com/qmk/qmk_firmware/pull/20563))
|
||||
* CannonKeys Moment Layout Macro Additions ([#20564](https://github.com/qmk/qmk_firmware/pull/20564))
|
||||
* CannonKeys Moment Hotswap Touch-Up ([#20565](https://github.com/qmk/qmk_firmware/pull/20565))
|
||||
* CannonKeys Nearfield Layout Macro Addition ([#20566](https://github.com/qmk/qmk_firmware/pull/20566))
|
||||
* CannonKeys Obliterated75 Layout Macro Additions ([#20567](https://github.com/qmk/qmk_firmware/pull/20567))
|
||||
* CannonKeys Onyx Layout Macro Additions ([#20568](https://github.com/qmk/qmk_firmware/pull/20568))
|
||||
* CannonKeys Rekt1800 Layout Macro Additions ([#20569](https://github.com/qmk/qmk_firmware/pull/20569))
|
||||
* CannonKeys Serenity Layout Macro Additions ([#20570](https://github.com/qmk/qmk_firmware/pull/20570))
|
||||
* CannonKeys Vector Layout Macro Additions ([#20571](https://github.com/qmk/qmk_firmware/pull/20571))
|
||||
* Carbo65 Community Layout support ([#20580](https://github.com/qmk/qmk_firmware/pull/20580))
|
||||
* cest73 TKM Layout Macro Additions ([#20583](https://github.com/qmk/qmk_firmware/pull/20583))
|
||||
* Charue Charon Layout Macro Additions ([#20585](https://github.com/qmk/qmk_firmware/pull/20585))
|
||||
* Charue Sunsetter R2 Layout Macro Additions ([#20586](https://github.com/qmk/qmk_firmware/pull/20586))
|
||||
* Remove `FLIP_HALF` layouts and move to data driven ([#20588](https://github.com/qmk/qmk_firmware/pull/20588))
|
||||
* update ymdk/id75/rules.mk for develop ([#20592](https://github.com/qmk/qmk_firmware/pull/20592))
|
||||
* CherryB Studio CB1800 Layout Macro Additions ([#20593](https://github.com/qmk/qmk_firmware/pull/20593))
|
||||
* CherryB Studio CB65 Layout Macro Additions ([#20594](https://github.com/qmk/qmk_firmware/pull/20594))
|
||||
* CherryB Studio CB87RGB Layout Macro Additions ([#20595](https://github.com/qmk/qmk_firmware/pull/20595))
|
||||
* CheckerBoards G_IDB60 Layout Macro Edits ([#20596](https://github.com/qmk/qmk_firmware/pull/20596))
|
||||
* CherryB Studio CB87v2 Layout Macro Additions ([#20597](https://github.com/qmk/qmk_firmware/pull/20597))
|
||||
* CX60 Community Layout Support ([#20598](https://github.com/qmk/qmk_firmware/pull/20598))
|
||||
* Demiurge Layout Macro Touch-Up ([#20599](https://github.com/qmk/qmk_firmware/pull/20599))
|
||||
* Ducky One 2 SF 1967ST Layout Macro Additions ([#20600](https://github.com/qmk/qmk_firmware/pull/20600))
|
||||
* Move `FORCE_NKRO` to data driven ([#20604](https://github.com/qmk/qmk_firmware/pull/20604))
|
||||
* dyz Synthesis60 Layout Macro Addition ([#20610](https://github.com/qmk/qmk_firmware/pull/20610))
|
||||
* DZTech Bocc Layout Macro Additions ([#20611](https://github.com/qmk/qmk_firmware/pull/20611))
|
||||
* E88 Layout Macro Additions ([#20612](https://github.com/qmk/qmk_firmware/pull/20612))
|
||||
* Emery65 Layout Macro Additions ([#20613](https://github.com/qmk/qmk_firmware/pull/20613))
|
||||
* EvyD13 MX5160 Layout Macro Additions ([#20614](https://github.com/qmk/qmk_firmware/pull/20614))
|
||||
* FJLabs AD65 Layout Macro Additions ([#20619](https://github.com/qmk/qmk_firmware/pull/20619))
|
||||
* FJLabs Avalon Layout Additions and Touch-Up ([#20620](https://github.com/qmk/qmk_firmware/pull/20620))
|
||||
* FJLabs Midway60 Layout Macro Additions ([#20621](https://github.com/qmk/qmk_firmware/pull/20621))
|
||||
* FJLabs Polaris Layout Additions and Touch-Up ([#20622](https://github.com/qmk/qmk_firmware/pull/20622))
|
||||
* FJLabs Sinanju WK Layout Additions and Touch-Up ([#20628](https://github.com/qmk/qmk_firmware/pull/20628))
|
||||
* LFK87 refactor ([#20635](https://github.com/qmk/qmk_firmware/pull/20635))
|
||||
* Fox Lab Time80 Layout Macro Additions ([#20636](https://github.com/qmk/qmk_firmware/pull/20636))
|
||||
* FJLabs Solanis Layout Macro Additions ([#20639](https://github.com/qmk/qmk_firmware/pull/20639))
|
||||
* GrayStudio Aero 75 Refactor and Touch-Up ([#20640](https://github.com/qmk/qmk_firmware/pull/20640))
|
||||
* Move `USB_MAX_POWER_CONSUMPTION` to data driven ([#20648](https://github.com/qmk/qmk_firmware/pull/20648))
|
||||
* `info.json` whitespace cleanups ([#20651](https://github.com/qmk/qmk_firmware/pull/20651))
|
||||
* Hand88 Layout Macro Additions ([#20657](https://github.com/qmk/qmk_firmware/pull/20657))
|
||||
* Cyberstar Handwired Layout Macro Additions ([#20658](https://github.com/qmk/qmk_firmware/pull/20658))
|
||||
* split_65 Handwired Layout Macro Addition and Touch-Up ([#20659](https://github.com/qmk/qmk_firmware/pull/20659))
|
||||
* Bebol Handwired Layout Macro Additions ([#20660](https://github.com/qmk/qmk_firmware/pull/20660))
|
||||
* Glacier Handwired Layout Macro Addition and Touch-Up ([#20661](https://github.com/qmk/qmk_firmware/pull/20661))
|
||||
* Koalafications Handwired Layout Macro Additions ([#20662](https://github.com/qmk/qmk_firmware/pull/20662))
|
||||
* The Galleon Handwired Layout Macro Additions ([#20663](https://github.com/qmk/qmk_firmware/pull/20663))
|
||||
* More `info.json` whitespace cleanups ([#20665](https://github.com/qmk/qmk_firmware/pull/20665))
|
||||
* Remove use of layout macros for LFKeyboards LED config ([#20666](https://github.com/qmk/qmk_firmware/pull/20666))
|
||||
* Helix rev2: remove 4 rows option ([#20667](https://github.com/qmk/qmk_firmware/pull/20667))
|
||||
* Wakizashi40 Handwired Touch-Up ([#20671](https://github.com/qmk/qmk_firmware/pull/20671))
|
||||
* yttyx: convert readme to utf-8 encoding ([#20672](https://github.com/qmk/qmk_firmware/pull/20672))
|
||||
* Alicia Cook Layout Macro Additions ([#20675](https://github.com/qmk/qmk_firmware/pull/20675))
|
||||
* Primus75 Layout Macro Additions ([#20676](https://github.com/qmk/qmk_firmware/pull/20676))
|
||||
* Volcano660 Layout Macro Additions ([#20677](https://github.com/qmk/qmk_firmware/pull/20677))
|
||||
* Iris Keyboards Iris60 Layout Macro Additions ([#20678](https://github.com/qmk/qmk_firmware/pull/20678))
|
||||
* Irene Layout Macro Additions ([#20679](https://github.com/qmk/qmk_firmware/pull/20679))
|
||||
* Iron180 Layout Macro Additions ([#20680](https://github.com/qmk/qmk_firmware/pull/20680))
|
||||
* kinesis/alvicstep: remove kicad project files ([#20681](https://github.com/qmk/qmk_firmware/pull/20681))
|
||||
* Remove more junk files and scripts ([#20682](https://github.com/qmk/qmk_firmware/pull/20682))
|
||||
* JKeys Design Gentleman65 Layout Macro Addition and Touch-Up ([#20684](https://github.com/qmk/qmk_firmware/pull/20684))
|
||||
* JKeys Design Gentleman65 Suited Edition Layout Macro Addition ([#20685](https://github.com/qmk/qmk_firmware/pull/20685))
|
||||
* add additional layouts to `dactyl_manuform` variants ([#20688](https://github.com/qmk/qmk_firmware/pull/20688))
|
||||
* TheDogKeyboard Layout Macro Addition ([#20689](https://github.com/qmk/qmk_firmware/pull/20689))
|
||||
* KBDfans Bella Soldered Layout Macro Additions ([#20691](https://github.com/qmk/qmk_firmware/pull/20691))
|
||||
* KBDfans Bounce75 Hotswap Touch-Up ([#20692](https://github.com/qmk/qmk_firmware/pull/20692))
|
||||
* KBDfans KBD66 Layout Additions and Refactor ([#20693](https://github.com/qmk/qmk_firmware/pull/20693))
|
||||
* KBDfans Odin RGB Touch-Up ([#20694](https://github.com/qmk/qmk_firmware/pull/20694))
|
||||
* KBDfans Odin Soldered Layout Additions and Touch-Up ([#20695](https://github.com/qmk/qmk_firmware/pull/20695))
|
||||
* keebzdotnet FMe Layout Additions ([#20696](https://github.com/qmk/qmk_firmware/pull/20696))
|
||||
* Kegen G-Boy Layout Additions ([#20697](https://github.com/qmk/qmk_firmware/pull/20697))
|
||||
* Escape Unicode characters in info.json ([#20698](https://github.com/qmk/qmk_firmware/pull/20698))
|
||||
* Kiko's Lab Ellora65 Layout Additions ([#20699](https://github.com/qmk/qmk_firmware/pull/20699))
|
||||
* Even more `info.json` whitespace cleanups ([#20703](https://github.com/qmk/qmk_firmware/pull/20703))
|
||||
* kkatano Bakeneko 65 V3 Layout Additions ([#20706](https://github.com/qmk/qmk_firmware/pull/20706))
|
||||
* kopibeng MNK65 Layout Additions ([#20708](https://github.com/qmk/qmk_firmware/pull/20708))
|
||||
* kopibeng Typ65+ Layout Additions ([#20710](https://github.com/qmk/qmk_firmware/pull/20710))
|
||||
* kopibeng XT60 Layout Additions ([#20711](https://github.com/qmk/qmk_firmware/pull/20711))
|
||||
* kopibeng XT60_SINGA Layout Additions ([#20712](https://github.com/qmk/qmk_firmware/pull/20712))
|
||||
* kopibeng XT8x Layout Additions ([#20713](https://github.com/qmk/qmk_firmware/pull/20713))
|
||||
* Lefty Touch-Up ([#20714](https://github.com/qmk/qmk_firmware/pull/20714))
|
||||
* Loki65 Layout Additions ([#20715](https://github.com/qmk/qmk_firmware/pull/20715))
|
||||
* Lucid Alexa Solder Layout Additions ([#20716](https://github.com/qmk/qmk_firmware/pull/20716))
|
||||
* Lucid Phantom Soldered Layout Additions ([#20717](https://github.com/qmk/qmk_firmware/pull/20717))
|
||||
* Leftover30 Layout Addition ([#20718](https://github.com/qmk/qmk_firmware/pull/20718))
|
||||
* Matrix Cain RE Touch-Up ([#20719](https://github.com/qmk/qmk_firmware/pull/20719))
|
||||
* Matrix Lab 8XV1.2 OG Layout Updates ([#20720](https://github.com/qmk/qmk_firmware/pull/20720))
|
||||
* Mechlovin Studio Hex6C Layout Additions ([#20722](https://github.com/qmk/qmk_firmware/pull/20722))
|
||||
* Mechlovin.Studio Rogue87 Rev.1 Layout Additions ([#20724](https://github.com/qmk/qmk_firmware/pull/20724))
|
||||
* Mechlovin.Studio Rouge87 Rev.1 Layout Additions ([#20725](https://github.com/qmk/qmk_firmware/pull/20725))
|
||||
* Mechlovin.Studio infinity87 Rev.1 Layout Additions ([#20726](https://github.com/qmk/qmk_firmware/pull/20726))
|
||||
* Mechlovin.Studio Infinity87 RGB Rev1 Layout Additions ([#20727](https://github.com/qmk/qmk_firmware/pull/20727))
|
||||
* Mechlovin9 Layout Addition ([#20728](https://github.com/qmk/qmk_firmware/pull/20728))
|
||||
* 1upkeyboards/pi50 WS2812_DI_PIN patch for develop ([#20731](https://github.com/qmk/qmk_firmware/pull/20731))
|
||||
* Mechlovin.Studio Infinity87 Rev.2 Layout Additions ([#20735](https://github.com/qmk/qmk_firmware/pull/20735))
|
||||
* Mechlovin.Studio Olly JF Layout Additions ([#20736](https://github.com/qmk/qmk_firmware/pull/20736))
|
||||
* Mechlovin Studio Serratus Layout Additions ([#20737](https://github.com/qmk/qmk_firmware/pull/20737))
|
||||
* MechWild Mercutio Layout Addition ([#20738](https://github.com/qmk/qmk_firmware/pull/20738))
|
||||
* MisterKnife Knife66 ISO Layout Addition ([#20739](https://github.com/qmk/qmk_firmware/pull/20739))
|
||||
* MNK1800s Layout Addition ([#20740](https://github.com/qmk/qmk_firmware/pull/20740))
|
||||
* MNK75 Layout Additions ([#20741](https://github.com/qmk/qmk_firmware/pull/20741))
|
||||
* Mode SixtyFive S Layout Additions ([#20742](https://github.com/qmk/qmk_firmware/pull/20742))
|
||||
* Mode SeventyFive H Layout Addition ([#20743](https://github.com/qmk/qmk_firmware/pull/20743))
|
||||
* Monstargear XO87 Soldered Layout Additions ([#20744](https://github.com/qmk/qmk_firmware/pull/20744))
|
||||
* MTBKeys MTB60 Solder Layout Additions ([#20745](https://github.com/qmk/qmk_firmware/pull/20745))
|
||||
* Nix Keyboards Day Off 60 Touch-Up and Layout Additions ([#20746](https://github.com/qmk/qmk_firmware/pull/20746))
|
||||
* Kastenwagen 1840 Layout Addition ([#20747](https://github.com/qmk/qmk_firmware/pull/20747))
|
||||
* Kastenwagen 48 Layout Addition ([#20748](https://github.com/qmk/qmk_firmware/pull/20748))
|
||||
* NovelKeys NK87 Touch-Up ([#20749](https://github.com/qmk/qmk_firmware/pull/20749))
|
||||
* NovelKeys NK87B Touch-Up ([#20750](https://github.com/qmk/qmk_firmware/pull/20750))
|
||||
* Noxary 378 Layout Addition ([#20751](https://github.com/qmk/qmk_firmware/pull/20751))
|
||||
* Noxary Valhalla Layout Addition ([#20752](https://github.com/qmk/qmk_firmware/pull/20752))
|
||||
* Nightly Boards/DeskDaily Daily60 Layout Additions ([#20753](https://github.com/qmk/qmk_firmware/pull/20753))
|
||||
* Odelia Touch-Up ([#20754](https://github.com/qmk/qmk_firmware/pull/20754))
|
||||
* One Key Co Dango40 Touch-Up and Layout Addition ([#20755](https://github.com/qmk/qmk_firmware/pull/20755))
|
||||
* P3D Glitch Layout Addition ([#20763](https://github.com/qmk/qmk_firmware/pull/20763))
|
||||
* Pearl Boards Pandora Layout Additions ([#20764](https://github.com/qmk/qmk_firmware/pull/20764))
|
||||
* Pearl Boards Pearl Layout Addition ([#20765](https://github.com/qmk/qmk_firmware/pull/20765))
|
||||
* support boards with APM32 instead of the STM32 ([#20770](https://github.com/qmk/qmk_firmware/pull/20770))
|
||||
* Pearl Boards Zeus Layout Additions ([#20773](https://github.com/qmk/qmk_firmware/pull/20773))
|
||||
* Peej Rosaline Staggered Layout Additions ([#20774](https://github.com/qmk/qmk_firmware/pull/20774))
|
||||
* plywrks Lune Layout Touch-Up ([#20775](https://github.com/qmk/qmk_firmware/pull/20775))
|
||||
* Project Keyboard Signature65 Layout Additions ([#20776](https://github.com/qmk/qmk_firmware/pull/20776))
|
||||
* protoTypist Allison Layout Additions ([#20777](https://github.com/qmk/qmk_firmware/pull/20777))
|
||||
* Prototypist J-01 Rev1 Layout Additions ([#20778](https://github.com/qmk/qmk_firmware/pull/20778))
|
||||
* Protozoa Cassini Layout Additions ([#20779](https://github.com/qmk/qmk_firmware/pull/20779))
|
||||
* Protozoa P.01 Layout Additions ([#20781](https://github.com/qmk/qmk_firmware/pull/20781))
|
||||
* QwertleKeys Calice Layout Addition ([#20782](https://github.com/qmk/qmk_firmware/pull/20782))
|
||||
* Ramlord WITF Layout Touch-Up and Addition ([#20783](https://github.com/qmk/qmk_firmware/pull/20783))
|
||||
* Rart45: rename LAYOUT_all to LAYOUT ([#20784](https://github.com/qmk/qmk_firmware/pull/20784))
|
||||
* Rart60 Layout Additions ([#20785](https://github.com/qmk/qmk_firmware/pull/20785))
|
||||
* Rart67 Layout Additions ([#20786](https://github.com/qmk/qmk_firmware/pull/20786))
|
||||
* Rart67M: rename LAYOUT_all to LAYOUT ([#20787](https://github.com/qmk/qmk_firmware/pull/20787))
|
||||
* RART75 Layout Additions ([#20788](https://github.com/qmk/qmk_firmware/pull/20788))
|
||||
* RART75 Hotswap Layout Additions ([#20789](https://github.com/qmk/qmk_firmware/pull/20789))
|
||||
* RART75M: rename LAYOUT_all to LAYOUT ([#20790](https://github.com/qmk/qmk_firmware/pull/20790))
|
||||
* RART80 Hotswap Layout Additions ([#20791](https://github.com/qmk/qmk_firmware/pull/20791))
|
||||
* Rartand Layout Additions ([#20799](https://github.com/qmk/qmk_firmware/pull/20799))
|
||||
* Rartlice: rename LAYOUT_all to LAYOUT ([#20800](https://github.com/qmk/qmk_firmware/pull/20800))
|
||||
* Ratio65 Hotswap: rename LAYOUT_all to LAYOUT_65_ansi_blocker ([#20801](https://github.com/qmk/qmk_firmware/pull/20801))
|
||||
* Ratio65 Solder Layout Additions ([#20802](https://github.com/qmk/qmk_firmware/pull/20802))
|
||||
* Specifying the default board file is redundant ([#20807](https://github.com/qmk/qmk_firmware/pull/20807))
|
||||
* RGBKB Pan Layout Additions ([#20809](https://github.com/qmk/qmk_firmware/pull/20809))
|
||||
* saevus cor Layout Additions ([#20810](https://github.com/qmk/qmk_firmware/pull/20810))
|
||||
* Clean up trailing commas from info.json ([#20812](https://github.com/qmk/qmk_firmware/pull/20812))
|
||||
* Enable LTO on salicylic acid 7skb to reduce size ([#20813](https://github.com/qmk/qmk_firmware/pull/20813))
|
||||
* Reduce compiled size for mt64rgb's via keymap ([#20814](https://github.com/qmk/qmk_firmware/pull/20814))
|
||||
* Reduce compiled size for prototypist oceanographer's via keymap ([#20816](https://github.com/qmk/qmk_firmware/pull/20816))
|
||||
* Sauce Mild Layout Additions ([#20818](https://github.com/qmk/qmk_firmware/pull/20818))
|
||||
* VCL x SawnsProjects VCL65 Layout Additions ([#20819](https://github.com/qmk/qmk_firmware/pull/20819))
|
||||
* senselessclay had60 Layout Additions ([#20820](https://github.com/qmk/qmk_firmware/pull/20820))
|
||||
* Space Holdings Nebula12B ([#20821](https://github.com/qmk/qmk_firmware/pull/20821))
|
||||
* SmithRune Iron180 Layout Additions ([#20822](https://github.com/qmk/qmk_firmware/pull/20822))
|
||||
* Stello65 Beta Layout Additions and Clean-Up ([#20824](https://github.com/qmk/qmk_firmware/pull/20824))
|
||||
* Studio Kestra Nue Layout Additions ([#20825](https://github.com/qmk/qmk_firmware/pull/20825))
|
||||
* Switchplate Peripherals 910 Layout Additions ([#20827](https://github.com/qmk/qmk_firmware/pull/20827))
|
||||
* TKC California Layout Addition and Touch-Up ([#20829](https://github.com/qmk/qmk_firmware/pull/20829))
|
||||
* TKC M0lly Layout Additions ([#20830](https://github.com/qmk/qmk_firmware/pull/20830))
|
||||
* TKC TKL A/B87 Layout Additions ([#20831](https://github.com/qmk/qmk_firmware/pull/20831))
|
||||
* Viendi 8L Layout Additions ([#20832](https://github.com/qmk/qmk_firmware/pull/20832))
|
||||
* Viktus Smolka Layout Additions ([#20833](https://github.com/qmk/qmk_firmware/pull/20833))
|
||||
* Viktus SP111 Layout Additions ([#20834](https://github.com/qmk/qmk_firmware/pull/20834))
|
||||
* Viktus SP_Mini Layout Additions ([#20835](https://github.com/qmk/qmk_firmware/pull/20835))
|
||||
* W1-AT Layout Additions ([#20842](https://github.com/qmk/qmk_firmware/pull/20842))
|
||||
* Weirdo Geminate60 Layout Additions ([#20843](https://github.com/qmk/qmk_firmware/pull/20843))
|
||||
* Cypher rev5 Layout Additions ([#20844](https://github.com/qmk/qmk_firmware/pull/20844))
|
||||
* Prophet Layout Additions ([#20845](https://github.com/qmk/qmk_firmware/pull/20845))
|
||||
* Tidy up encoder_map directions ([#20847](https://github.com/qmk/qmk_firmware/pull/20847))
|
||||
* Rama Works Koyu Community Layout Support ([#20848](https://github.com/qmk/qmk_firmware/pull/20848))
|
||||
* Rama Works M65-B Community Layout Support ([#20850](https://github.com/qmk/qmk_firmware/pull/20850))
|
||||
* Rama Works M65-BX Community Layout Support ([#20851](https://github.com/qmk/qmk_firmware/pull/20851))
|
||||
* Rama Works U80-A Community Layout Support ([#20853](https://github.com/qmk/qmk_firmware/pull/20853))
|
||||
* Wilba Tech WT60-B Community Layout Support ([#20854](https://github.com/qmk/qmk_firmware/pull/20854))
|
||||
* Wilba Tech WT60-BX Layout Additions and Touch-Up ([#20855](https://github.com/qmk/qmk_firmware/pull/20855))
|
||||
* Wilba Tech WT60-C Community Layout Support ([#20858](https://github.com/qmk/qmk_firmware/pull/20858))
|
||||
* Wilba Tech WT60-D Layout Addition and Touch-Up ([#20859](https://github.com/qmk/qmk_firmware/pull/20859))
|
||||
* Wilba Tech WT60-G Community Layout Support ([#20860](https://github.com/qmk/qmk_firmware/pull/20860))
|
||||
* Wilba Tech WT60-G2 Community Layout Support ([#20861](https://github.com/qmk/qmk_firmware/pull/20861))
|
||||
* Wilba Tech WT60-H2: rename LAYOUT_all to LAYOUT_60_ansi_tsangan_split_rshift ([#20864](https://github.com/qmk/qmk_firmware/pull/20864))
|
||||
* Wilba Tech WT60-XT Layout Additions and Touch-Up ([#20865](https://github.com/qmk/qmk_firmware/pull/20865))
|
||||
* Wilba Tech WT65-A Community Layout Support and Touch-Up ([#20866](https://github.com/qmk/qmk_firmware/pull/20866))
|
||||
* Wilba Tech WT65-B Layout Addition and Touch-Up ([#20867](https://github.com/qmk/qmk_firmware/pull/20867))
|
||||
* Wilba Tech WT65-F Community Layout Support and Touch-Up ([#20869](https://github.com/qmk/qmk_firmware/pull/20869))
|
||||
* Wilba Tech WT65-FX Community Layout Support ([#20870](https://github.com/qmk/qmk_firmware/pull/20870))
|
||||
* Wilba Tech WT65-G Layout Additions and Touch-Up ([#20871](https://github.com/qmk/qmk_firmware/pull/20871))
|
||||
* Wilba Tech WT65-G2 Layout Additions and Touch-Up ([#20872](https://github.com/qmk/qmk_firmware/pull/20872))
|
||||
* Wilba Tech WT65-XT: rename LAYOUT_all to LAYOUT_65_xt_ansi_blocker_tsangan ([#20873](https://github.com/qmk/qmk_firmware/pull/20873))
|
||||
* Wilba Tech WT65-XTX Layout Additions and Touch-Up ([#20874](https://github.com/qmk/qmk_firmware/pull/20874))
|
||||
* Wilba Tech WT69-A Layout Addition and Touch-Up ([#20875](https://github.com/qmk/qmk_firmware/pull/20875))
|
||||
* Wilba Tech WT70-JB Layout Addition and Touch-Up ([#20876](https://github.com/qmk/qmk_firmware/pull/20876))
|
||||
* Wilba Tech WT75-A Layout Additions and Touch-Up ([#20877](https://github.com/qmk/qmk_firmware/pull/20877))
|
||||
* Wilba Tech WT75-B Layout Additions and Touch-Up ([#20878](https://github.com/qmk/qmk_firmware/pull/20878))
|
||||
* Wilba Tech WT75-C Layout Additions and Touch-Up ([#20879](https://github.com/qmk/qmk_firmware/pull/20879))
|
||||
* Wilba Tech WT80-G Layout Additions and Touch-Up ([#20880](https://github.com/qmk/qmk_firmware/pull/20880))
|
||||
* WinKeys Mini Winni: rename LAYOUT_all to LAYOUT_ortho_2x4 ([#20881](https://github.com/qmk/qmk_firmware/pull/20881))
|
||||
* Scarlet Bandana Layout Additions ([#20882](https://github.com/qmk/qmk_firmware/pull/20882))
|
||||
* Winkeyless B87 Community Layout Support ([#20884](https://github.com/qmk/qmk_firmware/pull/20884))
|
||||
* Xelus AkiS Layout Additions ([#20885](https://github.com/qmk/qmk_firmware/pull/20885))
|
||||
* Xelus Dharma Layout Additions ([#20886](https://github.com/qmk/qmk_firmware/pull/20886))
|
||||
* Xelus Kangaroo Layout Additions ([#20887](https://github.com/qmk/qmk_firmware/pull/20887))
|
||||
* Xelus La+ Layout Addition ([#20888](https://github.com/qmk/qmk_firmware/pull/20888))
|
||||
* Xelus Pachi Mini 32U4 Community Layout Support ([#20889](https://github.com/qmk/qmk_firmware/pull/20889))
|
||||
* Xelus Pachi rev1 Community Layout Support ([#20891](https://github.com/qmk/qmk_firmware/pull/20891))
|
||||
* Xelus Trinity XT TKL Layout Additions ([#20892](https://github.com/qmk/qmk_firmware/pull/20892))
|
||||
* Xelus Valor FRL TKL Layout Additions ([#20893](https://github.com/qmk/qmk_firmware/pull/20893))
|
||||
* YDKB Chili Community Layout Support ([#20895](https://github.com/qmk/qmk_firmware/pull/20895))
|
||||
* YDKB Grape Layout Additions ([#20899](https://github.com/qmk/qmk_firmware/pull/20899))
|
||||
* YMDK Wings Layout Addition ([#20900](https://github.com/qmk/qmk_firmware/pull/20900))
|
||||
* YMDK Wings Hotswap: rename LAYOUT_all to LAYOUT ([#20901](https://github.com/qmk/qmk_firmware/pull/20901))
|
||||
* YMDK YM68 Community Layout Support ([#20906](https://github.com/qmk/qmk_firmware/pull/20906))
|
||||
* Yugo-M Controller Layout Additions ([#20907](https://github.com/qmk/qmk_firmware/pull/20907))
|
||||
* Zicodia TKLFRLNRLMLAO Layout Addition ([#20908](https://github.com/qmk/qmk_firmware/pull/20908))
|
||||
* ZTBoards After Layout Addition ([#20912](https://github.com/qmk/qmk_firmware/pull/20912))
|
||||
* ZTBoards Noon Layout Addition ([#20913](https://github.com/qmk/qmk_firmware/pull/20913))
|
||||
* SawnsProjects Amber80 Solder Community Layout Support ([#20917](https://github.com/qmk/qmk_firmware/pull/20917))
|
||||
* Pearl Boards Atlas Layout Additions ([#20918](https://github.com/qmk/qmk_firmware/pull/20918))
|
||||
* Xiudi XD004: rename LAYOUT_all to LAYOUT_ortho_1x4 ([#20919](https://github.com/qmk/qmk_firmware/pull/20919))
|
||||
* Wilba Tech WT80-BC Community Layout Support ([#20920](https://github.com/qmk/qmk_firmware/pull/20920))
|
||||
* 4pplet Eagle Viper REP Rev B Community Layout Support ([#20921](https://github.com/qmk/qmk_firmware/pull/20921))
|
||||
* FR4Boards unix60 Layout Additions ([#20926](https://github.com/qmk/qmk_firmware/pull/20926))
|
||||
* MC-76K: rename LAYOUT_all to LAYOUT ([#20927](https://github.com/qmk/qmk_firmware/pull/20927))
|
||||
* Mechlovin Studio Jay60 Community Layout Support ([#20928](https://github.com/qmk/qmk_firmware/pull/20928))
|
||||
* MisterKnife Knife66 Layout Additions ([#20929](https://github.com/qmk/qmk_firmware/pull/20929))
|
||||
* MisterKnife Knife66 ISO Layout Additions II ([#20930](https://github.com/qmk/qmk_firmware/pull/20930))
|
||||
* 4pplet Waffling80 Community Layout Support and Touch-Up ([#20932](https://github.com/qmk/qmk_firmware/pull/20932))
|
||||
* Acheron Elongate Delta: rename LAYOUT_all to LAYOUT ([#20956](https://github.com/qmk/qmk_firmware/pull/20956))
|
||||
* ADPenrose Akemipad Layout Addition ([#20957](https://github.com/qmk/qmk_firmware/pull/20957))
|
||||
* ADPenrose Shisaku: rename LAYOUT_all to LAYOUT ([#20958](https://github.com/qmk/qmk_firmware/pull/20958))
|
||||
* AEBoards Aegis Layout Additions ([#20960](https://github.com/qmk/qmk_firmware/pull/20960))
|
||||
* rart/rart80:via: restore rules.mk after #20334 ([#21002](https://github.com/qmk/qmk_firmware/pull/21002))
|
||||
* Remove HHKB RN42 code ([#21007](https://github.com/qmk/qmk_firmware/pull/21007))
|
||||
* Move `thekey` to Drop vendor folder ([#21032](https://github.com/qmk/qmk_firmware/pull/21032))
|
||||
|
||||
Keyboard fixes:
|
||||
* userspace/community layout fixes ([#19998](https://github.com/qmk/qmk_firmware/pull/19998))
|
||||
* Fix layout macro keys with no matrix position ([#20033](https://github.com/qmk/qmk_firmware/pull/20033))
|
||||
* Restore matrix pins for ep/40 ([#20083](https://github.com/qmk/qmk_firmware/pull/20083))
|
||||
* kbdfans/tiger80: remove duplicate keys in info.json ([#20148](https://github.com/qmk/qmk_firmware/pull/20148))
|
||||
* Fixup z70ultra — replace mis-removed file ([#20157](https://github.com/qmk/qmk_firmware/pull/20157))
|
||||
* Fixup CI build for F103C6 onekey. ([#20188](https://github.com/qmk/qmk_firmware/pull/20188))
|
||||
* Fix layouts containing keys with multiple matrix positions ([#20191](https://github.com/qmk/qmk_firmware/pull/20191))
|
||||
* Fix some more missing `#pragma once`s ([#20241](https://github.com/qmk/qmk_firmware/pull/20241))
|
||||
* Fixup CI build for `nack`. ([#20292](https://github.com/qmk/qmk_firmware/pull/20292))
|
||||
* Fixup Pointing device functions ([#20311](https://github.com/qmk/qmk_firmware/pull/20311))
|
||||
* Fix a handful of CLI errors ([#20321](https://github.com/qmk/qmk_firmware/pull/20321))
|
||||
* Fix API errors ([#20326](https://github.com/qmk/qmk_firmware/pull/20326))
|
||||
* Set up DEFAULT_FOLDER for primekb/meridian ([#20367](https://github.com/qmk/qmk_firmware/pull/20367))
|
||||
* Fix up via keymap builds. ([#20383](https://github.com/qmk/qmk_firmware/pull/20383))
|
||||
* Fix up via keymap builds. ([#20397](https://github.com/qmk/qmk_firmware/pull/20397))
|
||||
* Fix some missing QMK_KEYBOARD_H includes in user keymaps ([#20417](https://github.com/qmk/qmk_firmware/pull/20417))
|
||||
* Update ymdk/id75 config ([#20432](https://github.com/qmk/qmk_firmware/pull/20432))
|
||||
* Fix info.json LTO and format encoder definitions ([#20456](https://github.com/qmk/qmk_firmware/pull/20456))
|
||||
* Fixup dymium65 RGB Pin on develop ([#20473](https://github.com/qmk/qmk_firmware/pull/20473))
|
||||
* Fixup missing include in mxss `via` keymap ([#20475](https://github.com/qmk/qmk_firmware/pull/20475))
|
||||
* Fix nk plus ws2812 config ([#20524](https://github.com/qmk/qmk_firmware/pull/20524))
|
||||
* cannonkeys/ellipse_hs: correct layout macro references ([#20577](https://github.com/qmk/qmk_firmware/pull/20577))
|
||||
* Remove use of layout macros for `music_map` ([#20634](https://github.com/qmk/qmk_firmware/pull/20634))
|
||||
* Vertex/angle65 WS2812 pin fix ([#20653](https://github.com/qmk/qmk_firmware/pull/20653))
|
||||
* Fix ws2812 pin for phantagom boards ([#20670](https://github.com/qmk/qmk_firmware/pull/20670))
|
||||
* Fixup 1upkeyboards/pi50 ([#20733](https://github.com/qmk/qmk_firmware/pull/20733))
|
||||
* Fix `test_json2c_no_json()` ([#20756](https://github.com/qmk/qmk_firmware/pull/20756))
|
||||
* Fix mxss rgblight.c compilation issues ([#20804](https://github.com/qmk/qmk_firmware/pull/20804))
|
||||
* Fixup paladin64 ([#20805](https://github.com/qmk/qmk_firmware/pull/20805))
|
||||
* Fixup dogtag ([#20808](https://github.com/qmk/qmk_firmware/pull/20808))
|
||||
* Fixup zwag75 ([#20923](https://github.com/qmk/qmk_firmware/pull/20923))
|
||||
* Fixup latinpadble ([#20924](https://github.com/qmk/qmk_firmware/pull/20924))
|
||||
* Add missing layout data for a handful of boards ([#20931](https://github.com/qmk/qmk_firmware/pull/20931))
|
||||
* Fixup evo70 ([#20949](https://github.com/qmk/qmk_firmware/pull/20949))
|
||||
* Fixup Crkbd default keymap ([#20962](https://github.com/qmk/qmk_firmware/pull/20962))
|
||||
* Fix key display on Corne OLED ([#21044](https://github.com/qmk/qmk_firmware/pull/21044))
|
||||
|
||||
Others:
|
||||
* Add layer-cycle example ([#19069](https://github.com/qmk/qmk_firmware/pull/19069))
|
||||
* Remove remnants of Vagrant. ([#20000](https://github.com/qmk/qmk_firmware/pull/20000))
|
||||
* Develop cleanup IS31FL3736 docs ([#20633](https://github.com/qmk/qmk_firmware/pull/20633))
|
||||
* Organise config/rules <-> info mappings ([#20723](https://github.com/qmk/qmk_firmware/pull/20723))
|
||||
* Add a change log for PR20584 ([#20998](https://github.com/qmk/qmk_firmware/pull/20998))
|
||||
|
||||
Bugs:
|
||||
* Strip whitespace from CONVERT_TO variables ([#19948](https://github.com/qmk/qmk_firmware/pull/19948))
|
||||
* Check all rows have the correct number of columns when parsing `g_led_config` ([#19954](https://github.com/qmk/qmk_firmware/pull/19954))
|
||||
* Fix OSMs getting stuck ([#20034](https://github.com/qmk/qmk_firmware/pull/20034))
|
||||
* Fix rgblight layers when animations aren't enabled ([#20097](https://github.com/qmk/qmk_firmware/pull/20097))
|
||||
* Fixed split keyboard issue where custom LED indicators could activate incorrect LEDs (#20203) ([#20204](https://github.com/qmk/qmk_firmware/pull/20204))
|
||||
* Reduce _validate complexity ([#20274](https://github.com/qmk/qmk_firmware/pull/20274))
|
||||
* `qmk info`: account for ISO enter when calculating layout X offset ([#20325](https://github.com/qmk/qmk_firmware/pull/20325))
|
||||
* Disable specific warnings to mitigate compilation problems with `KEEP_INTERMEDIATES=yes`. ([#20339](https://github.com/qmk/qmk_firmware/pull/20339))
|
||||
* Fix compilation issue with Swap Hands and Encoder Map ([#20348](https://github.com/qmk/qmk_firmware/pull/20348))
|
||||
* Fix preprocessor condition for SPLIT_HAPTIC_ENABLE ([#20411](https://github.com/qmk/qmk_firmware/pull/20411))
|
||||
* Fix compilation issues with PS/2 driver on F4x1 controllers ([#20433](https://github.com/qmk/qmk_firmware/pull/20433))
|
||||
* Fix capital letters not getting sent with sendstring_swiss_fr.h ([#20515](https://github.com/qmk/qmk_firmware/pull/20515))
|
||||
* Duplicate board files for blok converter ([#20629](https://github.com/qmk/qmk_firmware/pull/20629))
|
||||
* Fix Mod-Tap combo regression ([#20669](https://github.com/qmk/qmk_firmware/pull/20669))
|
||||
* Revert use of legacy wear leveling driver now ChibiOS is fixed ([#20806](https://github.com/qmk/qmk_firmware/pull/20806))
|
||||
* Fix compilation error introduced by #20669 ([#20849](https://github.com/qmk/qmk_firmware/pull/20849))
|
||||
* Fix English word list retrieval in qmk generate-autocorrect-data ([#20915](https://github.com/qmk/qmk_firmware/pull/20915))
|
||||
* Improve keymap folder resolution ([#20981](https://github.com/qmk/qmk_firmware/pull/20981))
|
||||
* Fix issue with Repeat Key-Combo test ([#21005](https://github.com/qmk/qmk_firmware/pull/21005))
|
||||
* `qmk info` - Remove printing of "Keyboard Folder" ([#21033](https://github.com/qmk/qmk_firmware/pull/21033))
|
305
docs/ChangeLog/20230827.md
Normal file
305
docs/ChangeLog/20230827.md
Normal 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))
|
@ -41,7 +41,6 @@
|
||||
* [Keymap Overview](keymap.md)
|
||||
* Development Environments
|
||||
* [Docker Guide](getting_started_docker.md)
|
||||
* [Vagrant Guide](getting_started_vagrant.md)
|
||||
* Flashing
|
||||
* [Flashing](flashing.md)
|
||||
* [Flashing ATmega32A (ps2avrgb)](flashing_bootloadhid.md)
|
||||
@ -71,6 +70,7 @@
|
||||
* [Macros](feature_macros.md)
|
||||
* [Mouse Keys](feature_mouse_keys.md)
|
||||
* [Programmable Button](feature_programmable_button.md)
|
||||
* [Repeat Key](feature_repeat_key.md)
|
||||
* [Space Cadet Shift](feature_space_cadet.md)
|
||||
* [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md)
|
||||
|
||||
@ -80,6 +80,7 @@
|
||||
* [Caps Word](feature_caps_word.md)
|
||||
* [Combos](feature_combo.md)
|
||||
* [Debounce API](feature_debounce_type.md)
|
||||
* [Digitizer](feature_digitizer.md)
|
||||
* [EEPROM](feature_eeprom.md)
|
||||
* [Key Lock](feature_key_lock.md)
|
||||
* [Key Overrides](feature_key_overrides.md)
|
||||
@ -115,7 +116,6 @@
|
||||
* [Bootmagic Lite](feature_bootmagic.md)
|
||||
* [Converters](feature_converters.md)
|
||||
* [Custom Matrix](custom_matrix.md)
|
||||
* [Digitizer](feature_digitizer.md)
|
||||
* [DIP Switch](feature_dip_switch.md)
|
||||
* [Encoders](feature_encoders.md)
|
||||
* [Haptic Feedback](feature_haptic_feedback.md)
|
||||
@ -139,7 +139,7 @@
|
||||
* Breaking Changes
|
||||
* [Overview](breaking_changes.md)
|
||||
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
|
||||
* [Most Recent ChangeLog](ChangeLog/20230226.md "QMK v0.20.0 - 2023 Feb 26")
|
||||
* [Most Recent ChangeLog](ChangeLog/20230827.md "QMK v0.22.0 - 2023 Aug 27")
|
||||
* [Past Breaking Changes](breaking_changes_history.md)
|
||||
|
||||
* C Development
|
||||
|
@ -10,27 +10,25 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
|
||||
|
||||
## What has been included in past Breaking Changes?
|
||||
|
||||
* [2023 Aug 27](ChangeLog/20230827.md)
|
||||
* [2023 May 28](ChangeLog/20230528.md)
|
||||
* [2023 Feb 26](ChangeLog/20230226.md)
|
||||
* [2022 Nov 26](ChangeLog/20221126.md)
|
||||
* [2022 Aug 27](ChangeLog/20220827.md)
|
||||
* [2022 May 28](ChangeLog/20220528.md)
|
||||
* [2022 Feb 26](ChangeLog/20220226.md)
|
||||
* [Older Breaking Changes](breaking_changes_history.md)
|
||||
|
||||
## When is the next Breaking Change?
|
||||
|
||||
The next Breaking Change is scheduled for May 28, 2023.
|
||||
The next Breaking Change is scheduled for November 26, 2023.
|
||||
|
||||
### Important Dates
|
||||
|
||||
* 2023 Feb 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
|
||||
* 2023 Apr 30 - `develop` closed to new PRs.
|
||||
* 2023 Apr 30 - Call for testers.
|
||||
* 2023 May 14 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
|
||||
* 2023 May 21 - `develop` is locked, only critical bugfix PRs merged.
|
||||
* 2023 May 26 - `master` is locked, no PRs merged.
|
||||
* 2023 May 28 - Merge `develop` to `master`.
|
||||
* 2023 May 28 - `master` is unlocked. PRs can be merged again.
|
||||
* 2023 Aug 27 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
|
||||
* 2023 Oct 29 - `develop` closed to new PRs.
|
||||
* 2023 Oct 29 - Call for testers.
|
||||
* 2023 Nov 5 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
|
||||
* 2023 Nov 19 - `develop` is locked, only critical bugfix PRs merged.
|
||||
* 2023 Nov 23 - `master` is locked, no PRs merged.
|
||||
* 2023 Nov 26 - Merge `develop` to `master`.
|
||||
* 2023 Nov 26 - `master` is unlocked. PRs can be merged again.
|
||||
|
||||
## What changes will be included?
|
||||
|
||||
@ -50,7 +48,7 @@ Criteria for acceptance:
|
||||
|
||||
Strongly suggested:
|
||||
|
||||
* The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20221126`.
|
||||
* The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20231126`.
|
||||
* 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.
|
||||
|
||||
@ -121,6 +119,7 @@ This happens immediately after the previous `develop` branch is merged to `maste
|
||||
* `git commit -m 'Branch point for <DATE> Breaking Change'`
|
||||
* `git tag breakpoint_<YYYY>_<MM>_<DD>`
|
||||
* `git push upstream breakpoint_<YYYY>_<MM>_<DD>`
|
||||
* `git push upstream develop`
|
||||
|
||||
* All submodules under `lib` now need to be checked against their QMK-based forks:
|
||||
* `git submodule foreach git log -n1`
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
This page links to all previous changelogs from the QMK Breaking Changes process.
|
||||
|
||||
* [2023 Aug 27](ChangeLog/20230827.md) - version 0.22.0
|
||||
* [2023 May 28](ChangeLog/20230528.md) - version 0.21.0
|
||||
* [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0
|
||||
* [2022 Nov 26](ChangeLog/20221126.md) - version 0.19.0
|
||||
* [2022 Aug 27](ChangeLog/20220827.md) - version 0.18.0
|
||||
|
@ -23,14 +23,6 @@ If it is determined that your submission is a breaking change, there are a few t
|
||||
|
||||
If you are contributing core code, and the only reason it needs to go through breaking changes is that you are updating keymaps to match your change, consider whether you can submit your feature in a way that the old keymaps continue to work. Then submit a separate PR that goes through the breaking changes process to remove the old code.
|
||||
|
||||
### Contribute a ChangeLog Entry
|
||||
|
||||
We require submissions that go through the Breaking Change process to include a changelog entry. The entry should be a short summary of the changes your pull request makes – [each section here started as a changelog](ChangeLog/20190830.md "n.b. This should link to the 2019 Aug 30 Breaking Changes doc - @noroadsleft").
|
||||
|
||||
Your changelog should be located at `docs/ChangeLog/YYYYMMDD/PR####.md`, where `YYYYMMDD` is the date on which QMK's breaking change branch – usually named `develop` – will be merged into the `master` branch, and `####` is the number of your pull request.
|
||||
|
||||
If your submission requires action on the part of users, your changelog should instruct users what action(s) must be taken, or link to a location that does so.
|
||||
|
||||
### Document Your Changes
|
||||
|
||||
Understanding the purpose for your submission, and possible implications or actions it will require can make the review process more straightforward. A changelog may suffice for this purpose, but more extensive changes may require a level of detail that is ill-suited for a changelog.
|
||||
|
@ -20,7 +20,7 @@ qmk compile [-c] <configuratorExport.json>
|
||||
qmk compile [-c] [-e <var>=<value>] [-j <num_jobs>] -kb <keyboard_name> -km <keymap_name>
|
||||
```
|
||||
|
||||
**Usage in Keyboard Directory**:
|
||||
**Usage in Keyboard Directory**:
|
||||
|
||||
Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap <keymap_name>`
|
||||
```
|
||||
@ -44,7 +44,7 @@ $ qmk compile
|
||||
or with optional keymap argument
|
||||
|
||||
```
|
||||
$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4
|
||||
$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4
|
||||
$ qmk compile -km 66_iso
|
||||
Ψ Compiling keymap with make clueboard/66/rev4:66_iso
|
||||
...
|
||||
@ -58,7 +58,7 @@ $ qmk compile
|
||||
...
|
||||
```
|
||||
|
||||
**Usage in Layout Directory**:
|
||||
**Usage in Layout Directory**:
|
||||
|
||||
Must be under `qmk_firmware/layouts/`, and in a keymap folder.
|
||||
```
|
||||
@ -149,6 +149,49 @@ To exit out into the parent shell, simply type `exit`.
|
||||
qmk cd
|
||||
```
|
||||
|
||||
## `qmk find`
|
||||
|
||||
This command allows for searching through keyboard/keymap targets, filtering by specific criteria. `info.json` and `rules.mk` files contribute to the search data, as well as keymap configurations, and the results can be filtered using "dotty" syntax matching the overall `info.json` file format.
|
||||
|
||||
For example, one could search for all keyboards using STM32F411:
|
||||
|
||||
```
|
||||
qmk find -f 'processor=STM32F411'
|
||||
```
|
||||
|
||||
...and one can further constrain the list to keyboards using STM32F411 as well as rgb_matrix support:
|
||||
|
||||
```
|
||||
qmk find -f 'processor=STM32F411' -f 'features.rgb_matrix=true'
|
||||
```
|
||||
|
||||
The following filter expressions are also supported:
|
||||
|
||||
- `exists(key)`: Match targets where `key` is present.
|
||||
- `absent(key)`: Match targets where `key` is not present.
|
||||
- `contains(key, value)`: Match targets where `key` contains `value`. Can be used for strings, arrays and object keys.
|
||||
- `length(key, value)`: Match targets where the length of `key` is `value`. Can be used for strings, arrays and objects.
|
||||
|
||||
You can also list arbitrary values for each matched target with `--print`:
|
||||
|
||||
```
|
||||
qmk find -f 'processor=STM32F411' -p 'keyboard_name' -p 'features.rgb_matrix'
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk find [-h] [-km KEYMAP] [-p PRINT] [-f FILTER]
|
||||
|
||||
options:
|
||||
-km KEYMAP, --keymap KEYMAP
|
||||
The keymap name to build. Default is 'default'.
|
||||
-p PRINT, --print PRINT
|
||||
For each matched target, print the value of the supplied info.json key. May be passed multiple times.
|
||||
-f FILTER, --filter FILTER
|
||||
Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight=true'. Valid functions are 'absent', 'contains', 'exists' and 'length'. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'.
|
||||
```
|
||||
|
||||
## `qmk console`
|
||||
|
||||
This command lets you connect to keyboard consoles to get debugging messages. It only works if your keyboard firmware has been compiled with `CONSOLE_ENABLE=yes`.
|
||||
@ -269,7 +312,8 @@ qmk json2c [-o OUTPUT] filename
|
||||
|
||||
## `qmk c2json`
|
||||
|
||||
Creates a keymap.json from a keymap.c.
|
||||
Creates a keymap.json from a keymap.c.
|
||||
|
||||
**Note:** Parsing C source files is not easy, therefore this subcommand may not work with your keymap. In some cases not using the C pre-processor helps.
|
||||
|
||||
**Usage**:
|
||||
@ -442,7 +486,7 @@ $ qmk import-kbfirmware ~/Downloads/gh62.json
|
||||
|
||||
## `qmk format-text`
|
||||
|
||||
This command formats text files to have proper line endings.
|
||||
This command formats text files to have proper line endings.
|
||||
|
||||
Every text file in the repository needs to have Unix (LF) line ending.
|
||||
If you are working on **Windows**, you must ensure that line endings are corrected in order to get your PRs merged.
|
||||
@ -453,7 +497,7 @@ qmk format-text
|
||||
|
||||
## `qmk format-c`
|
||||
|
||||
This command formats C code using clang-format.
|
||||
This command formats C code using clang-format.
|
||||
|
||||
Run it with no arguments to format all core code that has been changed. Default checks `origin/master` with `git diff`, branch can be changed using `-b <branch_name>`
|
||||
|
||||
@ -556,7 +600,7 @@ qmk kle2json [-f] <filename>
|
||||
**Examples**:
|
||||
|
||||
```
|
||||
$ qmk kle2json kle.txt
|
||||
$ qmk kle2json kle.txt
|
||||
☒ File info.json already exists, use -f or --force to overwrite.
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
* 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.
|
||||
* Good: if (condition) { return false; }
|
||||
* Bad: if (condition) return false;
|
||||
* Good: `if (condition) { return false; }`
|
||||
* Bad: `if (condition) return false;`
|
||||
* We encourage use of C style comments: `/* */`
|
||||
* Think of them as a story describing the feature
|
||||
* Use them liberally to explain why particular decisions were made.
|
||||
|
@ -43,6 +43,8 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
|
||||
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
|
||||
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
|
||||
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
|
||||
* [STM32H723](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
|
||||
* [STM32H733](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
|
||||
* [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
|
||||
* [STM32L422](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
|
||||
* [STM32L432](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
|
||||
|
@ -150,7 +150,7 @@ If you define these options you will enable the associated feature, which may in
|
||||
* `#define TAPPING_TERM_PER_KEY`
|
||||
* enables handling for per key `TAPPING_TERM` settings
|
||||
* `#define RETRO_TAPPING`
|
||||
* tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release
|
||||
* tap anyway, even after `TAPPING_TERM`, if there was no other key interruption between press and release
|
||||
* See [Retro Tapping](tap_hold.md#retro-tapping) for details
|
||||
* `#define RETRO_TAPPING_PER_KEY`
|
||||
* enables handling for per key `RETRO_TAPPING` settings
|
||||
@ -161,9 +161,6 @@ If you define these options you will enable the associated feature, which may in
|
||||
* See [Permissive Hold](tap_hold.md#permissive-hold) for details
|
||||
* `#define PERMISSIVE_HOLD_PER_KEY`
|
||||
* enabled handling for per key `PERMISSIVE_HOLD` settings
|
||||
* `#define IGNORE_MOD_TAP_INTERRUPT`
|
||||
* makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys.
|
||||
* See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for details
|
||||
* `#define QUICK_TAP_TERM 100`
|
||||
* tap-then-hold timing to use a dual role key to repeat keycode
|
||||
* See [Quick Tap Term](tap_hold.md#quick-tap-term)
|
||||
@ -189,8 +186,6 @@ If you define these options you will enable the associated feature, which may in
|
||||
* how long before oneshot times out
|
||||
* `#define ONESHOT_TAP_TOGGLE 2`
|
||||
* how many taps before oneshot toggle is triggered
|
||||
* `#define COMBO_COUNT 2`
|
||||
* Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature. Or leave it undefined and programmatically set the count.
|
||||
* `#define COMBO_TERM 200`
|
||||
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
|
||||
* `#define COMBO_MUST_HOLD_MODS`
|
||||
@ -217,7 +212,7 @@ If you define these options you will enable the associated feature, which may in
|
||||
|
||||
## RGB Light Configuration
|
||||
|
||||
* `#define RGB_DI_PIN D7`
|
||||
* `#define WS2812_DI_PIN D7`
|
||||
* pin the DI on the WS2812 is hooked-up to
|
||||
* `#define RGBLIGHT_LAYERS`
|
||||
* Lets you define [lighting layers](feature_rgblight.md?id=lighting-layers) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state.
|
||||
@ -233,7 +228,7 @@ If you define these options you will enable the associated feature, which may in
|
||||
* `#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
|
||||
* `#define RGBLED_SPLIT { 6, 6 }`
|
||||
* number of LEDs connected that are directly wired to `RGB_DI_PIN` on each half of a split keyboard
|
||||
* number of LEDs connected that are directly wired to the RGB pin on each half of a split keyboard
|
||||
* First value indicates number of LEDs for left half, second value is for the right half
|
||||
* When RGBLED_SPLIT is defined, RGBLIGHT_SPLIT is implicitly defined.
|
||||
* `#define RGBLIGHT_HUE_STEP 12`
|
||||
@ -444,7 +439,7 @@ Use these to enable or disable building certain features. The more you have enab
|
||||
* `UNICODE_ENABLE`
|
||||
* Unicode
|
||||
* `BLUETOOTH_ENABLE`
|
||||
* Current options are BluefruitLE, RN42
|
||||
* Current options are bluefruit_le, rn42
|
||||
* `SPLIT_KEYBOARD`
|
||||
* Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
|
||||
* `CUSTOM_MATRIX`
|
||||
|
@ -36,7 +36,7 @@ If you need help you can [open an issue](https://github.com/qmk/qmk_firmware/iss
|
||||
Never made an open source contribution before? Wondering how contributions work in QMK? Here's a quick rundown!
|
||||
|
||||
0. Sign up for a [GitHub](https://github.com) account.
|
||||
1. Put together a keymap to contribute, [find an issue](https://github.com/qmk/qmk_firmware/issues) you are interested in addressing, or [a feature](https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) you would like to add.
|
||||
1. [Find an issue](https://github.com/qmk/qmk_firmware/issues) you are interested in addressing, or [a feature](https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) you would like to add.
|
||||
2. Fork the repository associated with the issue to your GitHub account. This means that you will have a copy of the repository under `your-GitHub-username/qmk_firmware`.
|
||||
3. Clone the repository to your local machine using `git clone https://github.com/github-username/repository-name.git`.
|
||||
4. If you're working on a new feature consider opening an issue to talk with us about the work you're about to undertake.
|
||||
@ -63,10 +63,11 @@ 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.
|
||||
|
||||
* **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.
|
||||
* Check for unnecessary whitespace with `git diff --check` before committing.
|
||||
* Make sure your code change actually compiles.
|
||||
* Keymaps: Make sure that `make keyboard:your_new_keymap` does not return any errors.
|
||||
* Keymaps: Make sure that `make keyboard:keymap` does not return any errors.
|
||||
* Keyboards: Make sure that `make keyboard:all` does not return any errors.
|
||||
* Core: Make sure that `make all` does not return any errors.
|
||||
* 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:
|
||||
@ -113,16 +114,6 @@ or if you only have Python 3 installed:
|
||||
|
||||
and navigating to `http://localhost:8936/`.
|
||||
|
||||
## Keymaps
|
||||
|
||||
Most first-time QMK contributors start with their personal keymaps. We try to keep keymap standards pretty casual (keymaps, after all, reflect the personality of their creators) but we do ask that you follow these guidelines to make it easier for others to discover and learn from your keymap.
|
||||
|
||||
* Write a `readme.md` using [the template](documentation_templates.md).
|
||||
* All Keymap PRs are squashed, so if you care about how your commits are squashed you should do it yourself
|
||||
* Do not lump features in with keymap PRs. Submit the feature first and then a second PR for the keymap.
|
||||
* Do not include `Makefile`s in your keymap folder (they're no longer used)
|
||||
* Update copyrights in file headers (look for `%YOUR_NAME%`)
|
||||
|
||||
## Keyboards
|
||||
|
||||
Keyboards are the raison d'être for QMK. Some keyboards are community maintained, while others are maintained by the people responsible for making a particular keyboard. The `readme.md` should tell you who maintains a particular keyboard. If you have questions relating to a particular keyboard you can [Open An Issue](https://github.com/qmk/qmk_firmware/issues) and tag the maintainer in your question.
|
||||
@ -130,7 +121,7 @@ Keyboards are the raison d'être for QMK. Some keyboards are community maintaine
|
||||
We also ask that you follow these guidelines:
|
||||
|
||||
* Write a `readme.md` using [the template](documentation_templates.md).
|
||||
* Keep the number of commits reasonable or we will squash your PR
|
||||
* Include a `default` keymap that provides a clean slate for users to start with when creating their own keymaps.
|
||||
* Do not lump core features in with new keyboards. Submit the feature first and then submit a separate PR for the keyboard.
|
||||
* Name `.c`/`.h` file after the immediate parent folder, eg `/keyboards/<kb1>/<kb2>/<kb2>.[ch]`
|
||||
* Do not include `Makefile`s in your keyboard folder (they're no longer used)
|
||||
|
@ -202,6 +202,62 @@ This function gets called at the end of all QMK processing, before starting the
|
||||
|
||||
Similar to `matrix_scan_*`, these are called as often as the MCU can handle. To keep your board responsive, it's suggested to do as little as possible during these function calls, potentially throtting their behaviour if you do indeed require implementing something special.
|
||||
|
||||
### Example `void housekeeping_task_user(void)` implementation
|
||||
|
||||
This example will show you how to use `void housekeeping_task_user(void)` to turn off [RGB Light](feature_rgblight.md). For RGB Matrix, the [builtin](https://docs.qmk.fm/#/feature_rgb_matrix?id=additional-configh-options) `RGB_MATRIX_TIMEOUT` should be used.
|
||||
|
||||
First, add the following lines to your keymap's `config.h`:
|
||||
|
||||
```c
|
||||
#define RGBLIGHT_SLEEP // enable rgblight_suspend() and rgblight_wakeup() in keymap.c
|
||||
#define RGBLIGHT_TIMEOUT 900000 // ms to wait until rgblight time out, 900K ms is 15min.
|
||||
```
|
||||
|
||||
Next, add the following code to your `keymap.c`:
|
||||
|
||||
```c
|
||||
static uint32_t key_timer; // timer for last keyboard activity, use 32bit value and function to make longer idle time possible
|
||||
static void refresh_rgb(void); // refreshes the activity timer and RGB, invoke whenever any activity happens
|
||||
static void check_rgb_timeout(void); // checks if enough time has passed for RGB to timeout
|
||||
bool is_rgb_timeout = false; // store if RGB has timed out or not in a boolean
|
||||
|
||||
void refresh_rgb(void) {
|
||||
key_timer = timer_read32(); // store time of last refresh
|
||||
if (is_rgb_timeout)
|
||||
{
|
||||
is_rgb_timeout = false;
|
||||
rgblight_wakeup();
|
||||
}
|
||||
}
|
||||
void check_rgb_timeout(void) {
|
||||
if (!is_rgb_timeout && timer_elapsed32(key_timer) > RGBLIGHT_TIMEOUT) // check if RGB has already timeout and if enough time has passed
|
||||
{
|
||||
rgblight_suspend();
|
||||
is_rgb_timeout = true;
|
||||
}
|
||||
}
|
||||
/* Then, call the above functions from QMK's built in post processing functions like so */
|
||||
/* Runs at the end of each scan loop, check if RGB timeout has occured or not */
|
||||
void housekeeping_task_user(void) {
|
||||
#ifdef RGBLIGHT_TIMEOUT
|
||||
check_rgb_timeout();
|
||||
#endif
|
||||
}
|
||||
/* Runs after each key press, check if activity occurred */
|
||||
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifdef RGBLIGHT_TIMEOUT
|
||||
if (record->event.pressed)
|
||||
refresh_rgb();
|
||||
#endif
|
||||
}
|
||||
/* Runs after each encoder tick, check if activity occurred */
|
||||
void post_encoder_update_user(uint8_t index, bool clockwise) {
|
||||
#ifdef RGBLIGHT_TIMEOUT
|
||||
refresh_rgb();
|
||||
#endif
|
||||
}
|
||||
```
|
||||
|
||||
# Keyboard Idling/Wake Code
|
||||
|
||||
If the board supports it, it can be "idled", by stopping a number of functions. A good example of this is RGB lights or backlights. This can save on power consumption, or may be better behavior for your keyboard.
|
||||
@ -209,7 +265,7 @@ If the board supports it, it can be "idled", by stopping a number of functions.
|
||||
This is controlled by two functions: `suspend_power_down_*` and `suspend_wakeup_init_*`, which are called when the system board is idled and when it wakes up, respectively.
|
||||
|
||||
|
||||
### Example suspend_power_down_user() and suspend_wakeup_init_user() Implementation
|
||||
### Example `suspend_power_down_user()` and `suspend_wakeup_init_user()` Implementation
|
||||
|
||||
|
||||
```c
|
||||
|
@ -79,8 +79,8 @@ If you are not sure how to edit this file or are not comfortable with Python [op
|
||||
|
||||
The final piece of the puzzle is providing your new option to the build system. This is done by generating two files:
|
||||
|
||||
* `.build/obj_<keyboard>/src/info_config.h`
|
||||
* `.build/obj_<keyboard>/src/rules.mk`
|
||||
* `.build/obj_<keyboard>_<keymap>/src/info_config.h`
|
||||
* `.build/obj_<keyboard>_<keymap>/src/rules.mk`
|
||||
|
||||
These two files are generated by the code here:
|
||||
|
||||
|
@ -37,9 +37,9 @@ For more information on bitwise operators in C, click [here](https://en.wikipedi
|
||||
|
||||
In practice, this means that you can check whether a given modifier is active with `get_mods() & MOD_BIT(KC_<modifier>)` (see the [list of modifier keycodes](keycodes_basic.md#modifiers)) or with `get_mods() & MOD_MASK_<modifier>` if the difference between left and right hand modifiers is not important and you want to match both. Same thing can be done for one-shot modifiers if you replace `get_mods()` with `get_oneshot_mods()`.
|
||||
|
||||
To check that *only* a specific set of mods is active at a time, AND the modifier state and your desired mod mask as explained above and compare the result to the mod mask itself: `get_mods() & <mod mask> == <mod mask>`.
|
||||
To check that *only* a specific set of mods is active at a time, use a simple equality operator: `get_mods() == <mod mask>`.
|
||||
|
||||
For example, let's say you want to trigger a piece of custom code if one-shot left control and one-shot left shift are on but every other one-shot mods are off. To do so, you can compose the desired mod mask by combining the mod bits for left control and shift with `(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))` and then plug it in: `get_oneshot_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT)) == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))`. Using `MOD_MASK_CS` instead for the mod bitmask would have forced you to press four modifier keys (both versions of control and shift) to fulfill the condition.
|
||||
For example, let's say you want to trigger a piece of custom code if one-shot left control and one-shot left shift are on but every other one-shot mods are off. To do so, you can compose the desired mod mask by combining the mod bits for left control and shift with `(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))` and then plug it in: `get_oneshot_mods() == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))`. Using `MOD_MASK_CS` instead for the mod bitmask would have forced you to press four modifier keys (both versions of control and shift) to fulfill the condition.
|
||||
|
||||
The full list of mod masks is as follows:
|
||||
|
||||
@ -91,7 +91,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
case KC_ESC:
|
||||
// Detect the activation of only Left Alt
|
||||
if ((get_mods() & MOD_BIT(KC_LALT)) == MOD_BIT(KC_LALT)) {
|
||||
if (get_mods() == MOD_BIT(KC_LALT)) {
|
||||
if (record->event.pressed) {
|
||||
// No need to register KC_LALT because it's already active.
|
||||
// The Alt modifier will apply on this KC_TAB.
|
||||
@ -160,6 +160,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
};
|
||||
```
|
||||
Alternatively, this can be done with [Key Overrides](feature_key_overrides?id=simple-example).
|
||||
|
||||
# Advanced topics :id=advanced-topics
|
||||
|
||||
@ -180,3 +181,7 @@ This page used to encompass a large set of features. We have moved many sections
|
||||
## Tap-Hold Configuration Options :id=tap-hold-configuration-options
|
||||
|
||||
* [Tap-Hold Configuration Options](tap_hold.md)
|
||||
|
||||
## Key Overrides :id=key-overrides
|
||||
|
||||
* [Key Overrides](feature_key_overrides.md)
|
||||
|
@ -133,7 +133,17 @@ groups in the below fallback switch.
|
||||
### NO_AUTO_SHIFT_SPECIAL (simple define)
|
||||
|
||||
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
|
||||
and /?
|
||||
/?, and the KC_TAB.
|
||||
|
||||
### NO_AUTO_SHIFT_TAB (simple define)
|
||||
|
||||
Do not Auto Shift KC_TAB but leave Auto Shift enabled for the other special
|
||||
characters.
|
||||
|
||||
### NO_AUTO_SHIFT_SYMBOLS (simple define)
|
||||
|
||||
Do not Auto Shift symbol keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
|
||||
and /?.
|
||||
|
||||
### NO_AUTO_SHIFT_NUMERIC (simple define)
|
||||
|
||||
@ -143,9 +153,13 @@ Do not Auto Shift numeric keys, zero through nine.
|
||||
|
||||
Do not Auto Shift alpha characters, which include A through Z.
|
||||
|
||||
### AUTO_SHIFT_ENTER (simple define)
|
||||
|
||||
Auto Shift the enter key.
|
||||
|
||||
### Auto Shift Per Key
|
||||
|
||||
There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
|
||||
There are functions that allows you to determine which keys should be autoshifted, much like the tap-hold keys.
|
||||
|
||||
The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`:
|
||||
|
||||
@ -172,9 +186,15 @@ bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_1 ... KC_0:
|
||||
# endif
|
||||
# ifndef NO_AUTO_SHIFT_SPECIAL
|
||||
# ifndef NO_AUTO_SHIFT_TAB
|
||||
case KC_TAB:
|
||||
case KC_MINUS ... KC_SLASH:
|
||||
case KC_NONUS_BACKSLASH:
|
||||
# endif
|
||||
# ifndef NO_AUTO_SHIFT_SYMBOLS
|
||||
case AUTO_SHIFT_SYMBOLS:
|
||||
# endif
|
||||
# endif
|
||||
# ifdef AUTO_SHIFT_ENTER
|
||||
case KC_ENT:
|
||||
# endif
|
||||
return true;
|
||||
}
|
||||
@ -192,6 +212,25 @@ Enables keyrepeat.
|
||||
|
||||
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
|
||||
|
||||
|
||||
### AUTO_SHIFT_ALPHA (predefined key group)
|
||||
|
||||
A predefined group of keys representing A through Z.
|
||||
|
||||
### AUTO_SHIFT_NUMERIC (predefined key group)
|
||||
|
||||
A predefined group of keys representing 0 through 9. Note, these are defined as
|
||||
1 through 0 since that is the order they normally appear in.
|
||||
|
||||
### AUTO_SHIFT_SYMBOLS (predefined key group)
|
||||
|
||||
A predefined group of keys representing symbolic characters which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
|
||||
and /?.
|
||||
|
||||
### AUTO_SHIFT_SPECIAL (predefined key group)
|
||||
|
||||
A predefined group of keys that combines AUTO_SHIFT_SYMBOLS and KC_TAB.
|
||||
|
||||
## Custom Shifted Values
|
||||
|
||||
Especially on small keyboards, the default shifted value for many keys is not
|
||||
|
@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
|
||||
|
||||
### Apply Autocorrect
|
||||
|
||||
Additionally, `apply_autocorrect(uint8_t backspaces, const char *str)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word).
|
||||
Additionally, `apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word), and the typo and corrected strings (complete words).
|
||||
|
||||
?> Due to the way code works (no notion of words, just a stream of letters), the `typo` and `correct` strings are a best bet and could be "wrong". For example you may get `wordtpyo` & `wordtypo` instead of the expected `tpyo` & `typo`.
|
||||
|
||||
#### Apply Autocorrect Example
|
||||
|
||||
@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut
|
||||
float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
|
||||
#endif
|
||||
|
||||
bool apply_autocorrect(uint8_t backspaces, const char *str) {
|
||||
bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(autocorrect_song);
|
||||
#endif
|
||||
@ -223,19 +225,34 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) {
|
||||
|
||||
?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters.
|
||||
|
||||
!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` or `SEND_STRING`.
|
||||
!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` nor `SEND_STRING`.
|
||||
|
||||
You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
|
||||
|
||||
```c
|
||||
bool apply_autocorrect(uint8_t backspaces, const char *str) {
|
||||
bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
|
||||
#ifdef OLED_ENABLE
|
||||
oled_write_P(PSTR("Auto-corrected"), false);
|
||||
#endif
|
||||
#ifdef CONSOLE_ENABLE
|
||||
printf("'%s' was corrected to '%s'\n", typo, correct);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Autocorrect Status
|
||||
|
||||
Additional user callback functions to manipulate Autocorrect:
|
||||
|
||||
| Function | Description |
|
||||
|----------------------------|----------------------------------------------|
|
||||
| `autocorrect_enable()` | Turns Autocorrect on. |
|
||||
| `autocorrect_disable()` | Turns Autocorrect off. |
|
||||
| `autocorrect_toggle()` | Toggles Autocorrect. |
|
||||
| `autocorrect_is_enabled()` | Returns true if Autocorrect is currently on. |
|
||||
|
||||
|
||||
## Appendix: Trie binary data format :id=appendix
|
||||
|
||||
This section details how the trie is serialized to byte data in autocorrect_data. You don’t need to care about this to use this autocorrection implementation. But it is documented for the record in case anyone is interested in modifying the implementation, or just curious how it works.
|
||||
|
@ -1,12 +1,12 @@
|
||||
# Backlighting :id=backlighting
|
||||
|
||||
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
|
||||
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB Underglow](feature_rgblight.md) and [RGB Matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
|
||||
|
||||
QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
|
||||
|
||||
The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
|
||||
## Usage :id=usage
|
||||
|
||||
Most keyboards have backlighting enabled by default if they support it, but if it is not working for you, check that your `rules.mk` includes the following:
|
||||
Most keyboards have backlighting enabled by default if they support it, but if it is not working for you (or you have added support), check that your `rules.mk` includes the following:
|
||||
|
||||
```make
|
||||
BACKLIGHT_ENABLE = yes
|
||||
@ -14,57 +14,23 @@ BACKLIGHT_ENABLE = yes
|
||||
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
Once enabled, the following keycodes below can be used to change the backlight level.
|
||||
|Key |Aliases |Description |
|
||||
|-------------------------------|---------|-----------------------------------|
|
||||
|`QK_BACKLIGHT_TOGGLE` |`BL_TOGG`|Turn the backlight on or off |
|
||||
|`QK_BACKLIGHT_STEP` |`BL_STEP`|Cycle through backlight levels |
|
||||
|`QK_BACKLIGHT_ON` |`BL_ON` |Set the backlight to max brightness|
|
||||
|`QK_BACKLIGHT_OFF` |`BL_OFF` |Turn the backlight off |
|
||||
|`QK_BACKLIGHT_UP` |`BL_UP` |Increase the backlight level |
|
||||
|`QK_BACKLIGHT_DOWN` |`BL_DOWN`|Decrease the backlight level |
|
||||
|`QK_BACKLIGHT_TOGGLE_BREATHING`|`BL_BRTG`|Toggle backlight breathing |
|
||||
|
||||
| Key | Aliases | Description |
|
||||
|---------------------------------|-----------|-------------------------------------|
|
||||
| `QK_BACKLIGHT_TOGGLE` | `BL_TOGG` | Turn the backlight on or off |
|
||||
| `QK_BACKLIGHT_STEP` | `BL_STEP` | Cycle through backlight levels |
|
||||
| `QK_BACKLIGHT_ON` | `BL_ON` | Set the backlight to max brightness |
|
||||
| `QK_BACKLIGHT_OFF` | `BL_OFF` | Turn the backlight off |
|
||||
| `QK_BACKLIGHT_UP` | `BL_UP` | Increase the backlight level |
|
||||
| `QK_BACKLIGHT_DOWN` | `BL_DOWN` | Decrease the backlight level |
|
||||
| `QK_BACKLIGHT_TOGGLE_BREATHING` | `BL_BRTG` | Toggle backlight breathing |
|
||||
## Basic Configuration :id=basic-configuration
|
||||
|
||||
## Functions :id=functions
|
||||
|
||||
These functions can be used to change the backlighting in custom code:
|
||||
|
||||
|Function |Description |
|
||||
|------------------------|--------------------------------------------|
|
||||
|`backlight_toggle()` |Turn the backlight on or off |
|
||||
|`backlight_enable()` |Turn the backlight on |
|
||||
|`backlight_disable()` |Turn the backlight off |
|
||||
|`backlight_step()` |Cycle through backlight levels |
|
||||
|`backlight_increase()` |Increase the backlight level |
|
||||
|`backlight_decrease()` |Decrease the backlight level |
|
||||
|`backlight_level(x)` |Sets the backlight level to specified level |
|
||||
|`get_backlight_level()` |Return the current backlight level |
|
||||
|`is_backlight_enabled()`|Return whether the backlight is currently on|
|
||||
|
||||
If backlight breathing is enabled (see below), the following functions are also available:
|
||||
|
||||
|Function |Description |
|
||||
|---------------------|--------------------------------------|
|
||||
|`breathing_toggle()` |Turn the backlight breathing on or off|
|
||||
|`breathing_enable()` |Turns on backlight breathing |
|
||||
|`breathing_disable()`|Turns off backlight breathing |
|
||||
|
||||
## Configuration :id=configuration
|
||||
|
||||
To select which driver to use, configure your `rules.mk` with the following:
|
||||
|
||||
```make
|
||||
BACKLIGHT_DRIVER = software
|
||||
```
|
||||
|
||||
Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help on individual drivers.
|
||||
|
||||
To configure the backlighting, `#define` these in your `config.h`:
|
||||
Add the following to your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|-----------------------------|------------------|-----------------------------------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LED(s) |
|
||||
|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LEDs |
|
||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|
||||
|`BACKLIGHT_CAPS_LOCK` |*Not defined* |Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||
|`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported |
|
||||
@ -76,124 +42,66 @@ To configure the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`.
|
||||
|
||||
### Backlight On State :id=backlight-on-state
|
||||
### "On" State :id=on-state
|
||||
|
||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
||||
|
||||
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
||||
To configure the "on" state of the backlight circuit, add the following to your `config.h`:
|
||||
|
||||
### AVR Driver :id=avr-driver
|
||||
|
||||
The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
|
||||
|
||||
```make
|
||||
BACKLIGHT_DRIVER = pwm
|
||||
```c
|
||||
#define BACKLIGHT_ON_STATE 0
|
||||
```
|
||||
|
||||
#### Caveats :id=avr-caveats
|
||||
|
||||
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
|
||||
### Multiple Backlight Pins :id=multiple-backlight-pins
|
||||
|
||||
Most keyboards have only one backlight pin which controls all backlight LEDs (especially if the backlight is connected to a hardware PWM pin).
|
||||
In software PWM, it is possible to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
|
||||
The `timer` and `software` drivers allow you to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
|
||||
|
||||
This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
|
||||
|
||||
To 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
|
||||
#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
|
||||
|
||||
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
|
||||
BACKLIGHT_DRIVER = custom
|
||||
```
|
||||
|
||||
Then implement any of these hooks:
|
||||
|
||||
```c
|
||||
void backlight_init_ports(void) {
|
||||
// Optional - runs on startup
|
||||
@ -211,10 +119,188 @@ 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|
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
|
||||
|
||||
|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
|
||||
|----------------------------------------------------------------|--------------------|---------------|--------------------------------|--------------|
|
||||
|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = RN42` |RN-42 |
|
||||
|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = BluefruitLE`|nRF51822 |
|
||||
|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
|
||||
|----------------------------------------------------------------|--------------------|---------------|---------------------------------|--------------|
|
||||
|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = rn42` |RN-42 |
|
||||
|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = bluefruit_le`|nRF51822 |
|
||||
|
||||
Not Supported Yet but possible:
|
||||
* [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479). [Possible tmk implementation found in](https://github.com/tmk/tmk_keyboard/issues/514)
|
||||
@ -32,7 +32,7 @@ Add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
BLUETOOTH_ENABLE = yes
|
||||
BLUETOOTH_DRIVER = BluefruitLE # or RN42
|
||||
BLUETOOTH_DRIVER = bluefruit_le # or rn42
|
||||
```
|
||||
|
||||
## Bluetooth Keycodes
|
||||
|
@ -90,6 +90,26 @@ by defining `IS_COMMAND()` in config.h:
|
||||
|
||||
## Customizing Caps Word :id=customizing-caps-word
|
||||
|
||||
### Invert on shift :id=invert-on-shift
|
||||
|
||||
By default, Caps Word turns off when Shift keys are pressed, considering them as
|
||||
word-breaking. Alternatively with the `CAPS_WORD_INVERT_ON_SHIFT` option,
|
||||
pressing the Shift key continues Caps Word and inverts the shift state. This
|
||||
is convenient for uncapitalizing one or a few letters within a word, for
|
||||
example with Caps Word on, typing "D, B, Shift+A, Shift+A, S" produces "DBaaS",
|
||||
or typing "P, D, F, Shift+S" produces "PDFs".
|
||||
|
||||
Enable it by adding in config.h
|
||||
|
||||
```c
|
||||
#define CAPS_WORD_INVERT_ON_SHIFT
|
||||
```
|
||||
|
||||
This option works with regular Shift keys `KC_LSFT` and `KC_RSFT`, mod-tap Shift
|
||||
keys, and one-shot Shift keys. Note that while Caps Word is on, one-shot Shift
|
||||
keys behave like regular Shift keys, and have effect only while they are held.
|
||||
|
||||
|
||||
### Idle timeout :id=idle-timeout
|
||||
|
||||
Caps Word turns off automatically if no keys are pressed for
|
||||
|
@ -4,15 +4,12 @@ The Combo feature is a chording type solution for adding custom actions. It lets
|
||||
|
||||
To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`.
|
||||
|
||||
Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). It is also possible to not define this and instead set the variable `COMBO_LEN` yourself. There's a trick where we don't need to think about this variable at all. More on this later.
|
||||
|
||||
|
||||
Then, in your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and its resulting action.
|
||||
|
||||
```c
|
||||
const uint16_t PROGMEM test_combo1[] = {KC_A, KC_B, COMBO_END};
|
||||
const uint16_t PROGMEM test_combo2[] = {KC_C, KC_D, COMBO_END};
|
||||
combo_t key_combos[COMBO_COUNT] = {
|
||||
combo_t key_combos[] = {
|
||||
COMBO(test_combo1, KC_ESC),
|
||||
COMBO(test_combo2, LCTL(KC_Z)), // keycodes with modifiers are possible too!
|
||||
};
|
||||
@ -20,31 +17,35 @@ combo_t key_combos[COMBO_COUNT] = {
|
||||
|
||||
This will send "Escape" if you hit the A and B keys, and Ctrl+Z when you hit the C and D keys.
|
||||
|
||||
As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to fire combos from ModTap keys and LayerTap keys. So in the above example you could have keys `LSFT_T(KC_A)` and `LT(_LAYER, KC_B)` and it would work. So Home Row Mods and Home Row Combos at same time is now a thing!
|
||||
|
||||
It is also now possible to overlap combos. Before, with the example below both combos would activate when all three keys were pressed. Now only the three key combo will activate.
|
||||
## Mod-Tap Support
|
||||
[Mod-Tap](mod_tap.md) feature is also supported together with combos. You will need to use the full Mod-Tap keycode in the combo definition, e.g.:
|
||||
|
||||
```c
|
||||
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), COMBO_END};
|
||||
const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), KC_C, COMBO_END};
|
||||
combo_t key_combos[COMBO_COUNT] = {
|
||||
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END};
|
||||
```
|
||||
|
||||
## Overlapping Combos
|
||||
It is possible to overlap combos. Before, with the example below both combos would activate when all three keys were pressed. Now only the three key combo will activate.
|
||||
|
||||
```c
|
||||
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END};
|
||||
const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(1, KC_B), KC_C, COMBO_END};
|
||||
combo_t key_combos[] = {
|
||||
COMBO(test_combo1, KC_ESC)
|
||||
COMBO(test_combo2, KC_TAB)
|
||||
};
|
||||
```
|
||||
|
||||
Executing more complex keycodes like ModTaps and LayerTaps is now also possible.
|
||||
|
||||
## Examples
|
||||
|
||||
If you want to add a list, then you'd use something like this:
|
||||
A long list of combos can be defined in an `enum` list:
|
||||
|
||||
```c
|
||||
enum combos {
|
||||
AB_ESC,
|
||||
JK_TAB,
|
||||
QW_SFT,
|
||||
SD_LAYER,
|
||||
SD_LAYER
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
|
||||
@ -52,7 +53,7 @@ const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
|
||||
const uint16_t PROGMEM qw_combo[] = {KC_Q, KC_W, COMBO_END};
|
||||
const uint16_t PROGMEM sd_combo[] = {KC_S, KC_D, COMBO_END};
|
||||
|
||||
combo_t key_combos[COMBO_COUNT] = {
|
||||
combo_t key_combos[] = {
|
||||
[AB_ESC] = COMBO(ab_combo, KC_ESC),
|
||||
[JK_TAB] = COMBO(jk_combo, KC_TAB),
|
||||
[QW_SFT] = COMBO(qw_combo, KC_LSFT),
|
||||
@ -61,15 +62,12 @@ combo_t key_combos[COMBO_COUNT] = {
|
||||
```
|
||||
|
||||
For a more complicated implementation, you can use the `process_combo_event` function to add custom handling.
|
||||
Additionally, this example shows how you can leave `COMBO_COUNT` undefined.
|
||||
|
||||
```c
|
||||
enum combo_events {
|
||||
EM_EMAIL,
|
||||
BSPC_LSFT_CLEAR,
|
||||
COMBO_LENGTH
|
||||
};
|
||||
uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead!
|
||||
|
||||
const uint16_t PROGMEM email_combo[] = {KC_E, KC_M, COMBO_END};
|
||||
const uint16_t PROGMEM clear_line_combo[] = {KC_BSPC, KC_LSFT, COMBO_END};
|
||||
@ -111,13 +109,13 @@ You can enable, disable and toggle the Combo feature on the fly. This is useful
|
||||
|`QK_COMBO_OFF` |`CM_OFF` |Turns off Combo feature |
|
||||
|`QK_COMBO_TOGGLE`|`CM_TOGG`|Toggles Combo feature on and off|
|
||||
|
||||
# Advanced Configuration
|
||||
## Advanced Configuration
|
||||
These configuration settings can be set in your `config.h` file.
|
||||
|
||||
## Combo Term
|
||||
### Combo Term
|
||||
By default, the timeout for the Combos to be recognized is set to 50ms. This can be changed if accidental combo misfires are happening or if you're having difficulties pressing keys at the same time. For instance, `#define COMBO_TERM 40` would set the timeout period for combos to 40ms.
|
||||
|
||||
## Buffer and state sizes
|
||||
### Buffer and state sizes
|
||||
If you're using long combos, or you have a lot of overlapping combos, you may run into issues with this, as the buffers may not be large enough to accommodate what you're doing. In this case, you can configure the sizes of the buffers used. Be aware, larger combo sizes and larger buffers will increase memory usage!
|
||||
|
||||
To configure the amount of keys a combo can be composed of, change the following:
|
||||
@ -138,13 +136,13 @@ Processing combos has two buffers, one for the key presses, another for the comb
|
||||
| `#define COMBO_KEY_BUFFER_LENGTH 8` | 8 (the key amount `(EXTRA_)EXTRA_LONG_COMBOS` gives) |
|
||||
| `#define COMBO_BUFFER_LENGTH 4` | 4 |
|
||||
|
||||
## Modifier Combos
|
||||
### Modifier Combos
|
||||
If a combo resolves to a Modifier, the window for processing the combo can be extended independently from normal combos. By default, this is disabled but can be enabled with `#define COMBO_MUST_HOLD_MODS`, and the time window can be configured with `#define COMBO_HOLD_TERM 150` (default: `TAPPING_TERM`). With `COMBO_MUST_HOLD_MODS`, you cannot tap the combo any more which makes the combo less prone to misfires.
|
||||
|
||||
## Strict key press order
|
||||
### Strict key press order
|
||||
By defining `COMBO_MUST_PRESS_IN_ORDER` combos only activate when the keys are pressed in the same order as they are defined in the key array.
|
||||
|
||||
## Per Combo Timing, Holding, Tapping and Key Press Order
|
||||
### Per Combo Timing, Holding, Tapping and Key Press Order
|
||||
For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, if it needs to be tapped, or if its keys need to be pressed in order.
|
||||
|
||||
For example, tap-only combos are useful if any (or all) of the underlying keys are mod-tap or layer-tap keys. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't activate. Instead the keys are processed separately as if the combo wasn't even there.
|
||||
@ -234,7 +232,7 @@ bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) {
|
||||
}
|
||||
```
|
||||
|
||||
## Generic hook to (dis)allow a combo activation
|
||||
### Generic hook to (dis)allow a combo activation
|
||||
|
||||
By defining `COMBO_SHOULD_TRIGGER` and its companying function `bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record)` you can block or allow combos to activate on the conditions of your choice.
|
||||
For example, you could disallow some combos on the base layer and allow them on another. Or disable combos on the home row when a timer is running.
|
||||
@ -254,38 +252,26 @@ bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode
|
||||
}
|
||||
```
|
||||
|
||||
## Variable Length Combos
|
||||
If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = ARRAY_SIZE(key_combos);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such:
|
||||
```c
|
||||
enum myCombos {
|
||||
...,
|
||||
COMBO_LENGTH
|
||||
};
|
||||
uint16_t COMBO_LEN = COMBO_LENGTH;
|
||||
```
|
||||
Regardless of the method used to declare `COMBO_LEN`, this also requires to convert the `combo_t key_combos[COMBO_COUNT] = {...};` line to `combo_t key_combos[] = {...};`.
|
||||
|
||||
|
||||
## Combo timer
|
||||
### Combo timer
|
||||
|
||||
Normally, the timer is started on the first key press and then reset on every subsequent key press within the `COMBO_TERM`.
|
||||
Inputting combos is relaxed like this, but also slightly more prone to accidental misfires.
|
||||
|
||||
The next two options alter the behaviour of the timer.
|
||||
|
||||
### `#define COMBO_STRICT_TIMER`
|
||||
#### `#define COMBO_STRICT_TIMER`
|
||||
|
||||
With `COMBO_STRICT_TIMER`, the timer is started only on the first key press.
|
||||
Inputting combos is now less relaxed; you need to make sure the full chord is pressed within the `COMBO_TERM`.
|
||||
Misfires are less common but if you type multiple combos fast, there is a
|
||||
chance that the latter ones might not activate properly.
|
||||
|
||||
### `#define COMBO_NO_TIMER`
|
||||
#### `#define COMBO_NO_TIMER`
|
||||
|
||||
By defining `COMBO_NO_TIMER`, the timer is disabled completely and combos are activated on the first key release.
|
||||
This also disables the "must hold" functionalities as they just wouldn't work at all.
|
||||
|
||||
## Customizable key releases
|
||||
### Customizable key releases
|
||||
|
||||
By defining `COMBO_PROCESS_KEY_RELEASE` and implementing the function `bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode)`, you can run your custom code on each key release after a combo was activated. For example you could change the RGB colors, activate haptics, or alter the modifiers.
|
||||
|
||||
@ -295,10 +281,8 @@ Here's an example where a combo resolves to two modifiers, and on key releases t
|
||||
|
||||
```c
|
||||
enum combos {
|
||||
AB_MODS,
|
||||
COMBO_LENGTH
|
||||
AB_MODS
|
||||
};
|
||||
uint16_t COMBO_LEN = COMBO_LENGTH;
|
||||
|
||||
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
|
||||
|
||||
@ -322,13 +306,13 @@ bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key
|
||||
return false;
|
||||
}
|
||||
```
|
||||
## Layer independent combos
|
||||
### Layer independent combos
|
||||
|
||||
If you, for example, use multiple base layers for different key layouts, one for QWERTY, and another one for Colemak, you might want your combos to work from the same key positions on all layers. Defining the same combos again for another layout is redundant and takes more memory. The solution is to just check the keycodes from one layer.
|
||||
|
||||
With `#define COMBO_ONLY_FROM_LAYER 0` in config.h, the combos' keys are always checked from layer `0`, even if other layers are active.
|
||||
|
||||
### Combo reference layers by layer.
|
||||
#### Combo reference layers by layer.
|
||||
|
||||
If not using `COMBO_ONLY_FROM_LAYER` it is possible to specify a
|
||||
combo reference layer for any layer using the `combo_ref_from_layer` hook.
|
||||
@ -385,7 +369,7 @@ In addition to the keycodes, there are a few functions that you can use to set t
|
||||
| `is_combo_enabled()` | Returns the status of the combo feature state (true or false) |
|
||||
|
||||
|
||||
# Dictionary Management
|
||||
## Dictionary Management
|
||||
|
||||
Having 3 places to update when adding new combos or altering old ones does become cumbersome when you have a lot of combos. We can alleviate this with some magic! ... If you consider C macros magic.
|
||||
First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, include the file `g/keymap_combo.h` in your `keymap.c`.
|
||||
@ -410,6 +394,4 @@ SUBS(TH_THE, "the", KC_T, KC_H) // SUBS uses SEND_STRING to output the give
|
||||
...
|
||||
```
|
||||
|
||||
Now, you can update only one place to add or alter combos. You don't even need to remember to update the `COMBO_COUNT` or the `COMBO_LEN` variables at all. Everything is taken care of. Magic!
|
||||
|
||||
For small to huge ready made dictionaries of combos, you can check out http://combos.gboards.ca/.
|
||||
|
@ -17,15 +17,16 @@ Currently the following converters are available:
|
||||
| `promicro` | `bit_c_pro` |
|
||||
| `promicro` | `stemcell` |
|
||||
| `promicro` | `bonsai_c4` |
|
||||
| `promicro` | `elite_pi` |
|
||||
| `promicro` | `rp2040_ce` |
|
||||
| `promicro` | `elite_pi` |
|
||||
| `promicro` | `helios` |
|
||||
| `promicro` | `liatris` |
|
||||
| `promicro` | `michi` |
|
||||
| `elite_c` | `stemcell` |
|
||||
| `elite_c` | `rp2040_ce` |
|
||||
| `elite_c` | `elite_pi` |
|
||||
| `elite_c` | `helios` |
|
||||
| `elite_c` | `liatris` |
|
||||
|
||||
See below for more in depth information on each converter.
|
||||
|
||||
@ -88,6 +89,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
|
||||
| [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` |
|
||||
| [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` |
|
||||
| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
|
||||
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
|
||||
|
||||
Converter summary:
|
||||
@ -104,6 +106,7 @@ Converter summary:
|
||||
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
|
||||
| `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` |
|
||||
| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
|
||||
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
|
||||
|
||||
### Proton C :id=proton_c
|
||||
@ -168,7 +171,7 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
|
||||
#define B0 PAL_LINE(GPIOA, 9)
|
||||
```
|
||||
|
||||
### RP2040 Community Edition - Elite-Pi and Helios :id=rp2040_ce
|
||||
### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
|
||||
|
||||
Feature set currently identical to [Adafruit KB2040](#kb2040).
|
||||
|
||||
@ -185,6 +188,7 @@ If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products
|
||||
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
|
||||
| [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` |
|
||||
| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
|
||||
|
||||
Converter summary:
|
||||
|
||||
@ -194,6 +198,7 @@ Converter summary:
|
||||
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
|
||||
| `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` |
|
||||
| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
|
||||
|
||||
### STeMCell :id=stemcell_elite
|
||||
|
||||
|
@ -57,78 +57,78 @@ susceptible to noise, you must choose a debounce method that will also mitigate
|
||||
if the scanning is slow, and you are using a timestamp-based algorithm, you might end up making a debouncing decision based on only two
|
||||
sampled values, which will limit the noise-resistance of the algorithm.
|
||||
* Currently all built-in debounce algorithms support timestamp-based debouncing only. In the future we might
|
||||
implement cycles-based debouncing, and it will be selectable via a ```config.h``` macro.
|
||||
implement cycles-based debouncing, and it will be selectable via a `config.h` macro.
|
||||
|
||||
2) Symmetric vs Asymmetric
|
||||
* Symmetric - apply the same debouncing algorithm, to both key-up and key-down events.
|
||||
* Recommended naming convention: ```sym_*```
|
||||
* Recommended naming convention: `sym_*`
|
||||
* Asymmetric - apply different debouncing algorithms to key-down and key-up events. E.g. Eager key-down, Defer key-up.
|
||||
* Recommended naming convention: ```asym_*``` followed by details of the type of algorithm in use, in order, for key-down and then key-up
|
||||
* Recommended naming convention: `asym_*` followed by details of the type of algorithm in use, in order, for key-down and then key-up
|
||||
|
||||
3) Eager vs Defer
|
||||
* Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored.
|
||||
* Eager algorithms are not noise-resistant.
|
||||
* Recommended naming conventions:
|
||||
* ```sym_eager_*```
|
||||
* ```asym_eager_*_*```: key-down is using eager algorithm
|
||||
* ```asym_*_eager_*```: key-up is using eager algorithm
|
||||
* `sym_eager_*`
|
||||
* `asym_eager_*_*`: key-down is using eager algorithm
|
||||
* `asym_*_eager_*`: key-up is using eager algorithm
|
||||
* Defer - wait for no changes for DEBOUNCE ms before reporting change.
|
||||
* Defer algorithms are noise-resistant
|
||||
* Recommended naming conventions:
|
||||
* ```sym_defer_*```
|
||||
* ```asym_defer_*_*```: key-down is using defer algorithm
|
||||
* ```asym_*_defer_*```: key-up is using defer algorithm
|
||||
* `sym_defer_*`
|
||||
* `asym_defer_*_*`: key-down is using defer algorithm
|
||||
* `asym_*_defer_*`: key-up is using defer algorithm
|
||||
|
||||
4) Global vs Per-Key vs Per-Row
|
||||
* Global - one timer for all keys. Any key change state affects global timer
|
||||
* Recommended naming convention: ```*_g```
|
||||
* Recommended naming convention: `*_g`
|
||||
* Per-key - one timer per key
|
||||
* Recommended naming convention: ```*_pk```
|
||||
* Recommended naming convention: `*_pk`
|
||||
* Per-row - one timer per row
|
||||
* Recommended naming convention: ```*_pr```
|
||||
* Recommended naming convention: `*_pr`
|
||||
* Per-key and per-row algorithms consume more resources (in terms of performance,
|
||||
and ram usage), but fast typists might prefer them over global.
|
||||
|
||||
## Debounce algorithms supported by QMK
|
||||
## Supported Debounce Algorithms
|
||||
|
||||
QMK supports multiple debounce algorithms through its debounce API.
|
||||
QMK supports multiple algorithms through its debounce API.
|
||||
|
||||
### Debounce selection
|
||||
### Debounce Time
|
||||
|
||||
| DEBOUNCE_TYPE | Description | What else is needed |
|
||||
| ------------- | --------------------------------------------------- | ----------------------------- |
|
||||
| Not defined | Use the default algorithm, currently sym_defer_g | Nothing |
|
||||
| custom | Use your own debounce code | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions |
|
||||
| Anything Else | Use another algorithm from quantum/debounce/* | Nothing |
|
||||
Default debounce time is 5 milliseconds and it can be changed with the following line in `config.h`:
|
||||
```
|
||||
#define DEBOUNCE 10
|
||||
```
|
||||
?> Setting `DEBOUNCE` to `0` will disable this feature.
|
||||
|
||||
**Regarding split keyboards**:
|
||||
The debounce code is compatible with split keyboards.
|
||||
### Debounce Method
|
||||
|
||||
### Selecting an included debouncing method
|
||||
Keyboards may select one of the already implemented debounce methods, by adding to ```rules.mk``` the following line:
|
||||
Keyboards may select one of the core debounce methods by adding the following line into `rules.mk`:
|
||||
```
|
||||
DEBOUNCE_TYPE = <name of algorithm>
|
||||
```
|
||||
Where name of algorithm is one of:
|
||||
* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed.
|
||||
* This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant.
|
||||
* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
|
||||
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
|
||||
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
|
||||
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
|
||||
* ```sym_defer_pr``` - debouncing per row. On any state change, a per-row timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that row, the entire row is pushed. Can improve responsiveness over `sym_defer_g` while being less susceptible than per-key debouncers to noise.
|
||||
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
|
||||
* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
|
||||
Name of algorithm is one of:
|
||||
|
||||
### A couple algorithms that could be implemented in the future:
|
||||
* ```sym_defer_pr```
|
||||
* ```sym_eager_g```
|
||||
| Algorithm | Description |
|
||||
| --------------------- | ----------- |
|
||||
| `sym_defer_g` | Debouncing per keyboard. On any state change, a global timer is set. When `DEBOUNCE` milliseconds of no changes has occurred, all input changes are pushed. This is the highest performance algorithm with lowest memory usage and is noise-resistant. |
|
||||
| `sym_defer_pr` | Debouncing per row. On any state change, a per-row timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that row, the entire row is pushed. This can improve responsiveness over `sym_defer_g` while being less susceptible to noise than per-key algorithm. |
|
||||
| `sym_defer_pk` | Debouncing per key. On any state change, a per-key timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that key, the key status change is pushed. |
|
||||
| `sym_eager_pr` | Debouncing per row. On any state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that row. |
|
||||
| `sym_eager_pk` | Debouncing per key. On any state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that key. |
|
||||
| `asym_eager_defer_pk` | Debouncing per key. On a key-down state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that key, the key-up status change is pushed. |
|
||||
|
||||
### Use your own debouncing code
|
||||
You have the option to implement you own debouncing algorithm. To do this:
|
||||
* Set ```DEBOUNCE_TYPE = custom``` in ```rules.mk```.
|
||||
* Add ```SRC += debounce.c``` in ```rules.mk```
|
||||
* Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples.
|
||||
?> `sym_defer_g` is the default if `DEBOUNCE_TYPE` is undefined.
|
||||
|
||||
?> `sym_eager_pr` is suitable for use in keyboards where refreshing `NUM_KEYS` 8-bit counters is computationally expensive or has low scan rate while fingers usually hit one row at a time. This could be appropriate for the ErgoDox models where the matrix is rotated 90°. Hence its "rows" are really columns and each finger only hits a single "row" at a time with normal usage.
|
||||
|
||||
### Implementing your own debouncing code
|
||||
|
||||
You have the option to implement you own debouncing algorithm with the following steps:
|
||||
|
||||
* Set `DEBOUNCE_TYPE = custom` in `rules.mk`.
|
||||
* Add `SRC += debounce.c` in `rules.mk`
|
||||
* Implement your own `debounce.c`. See `quantum/debounce` for examples.
|
||||
* Debouncing occurs after every raw matrix scan.
|
||||
* Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly.
|
||||
* If the algorithm might be applicable to other keyboards, please consider adding it to ```quantum/debounce```
|
||||
* Use num_rows instead of MATRIX_ROWS to support split keyboards correctly.
|
||||
* If your custom algorithm is applicable to other keyboards, please consider making a pull request.
|
||||
|
@ -59,7 +59,7 @@ There are a number of hooks that you can use to add custom functionality and fee
|
||||
|
||||
Note, that direction indicates which macro it is, with `1` being Macro 1, `-1` being Macro 2, and 0 being no macro.
|
||||
|
||||
* `dynamic_macro_record_start_user(void)` - Triggered when you start recording a macro.
|
||||
* `dynamic_macro_record_start_user(int8_t direction)` - Triggered when you start recording a macro.
|
||||
* `dynamic_macro_play_user(int8_t direction)` - Triggered when you play back a macro.
|
||||
* `dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record)` - Triggered on each keypress while recording a macro.
|
||||
* `dynamic_macro_record_end_user(int8_t direction)` - Triggered when the macro recording is stopped.
|
||||
|
@ -81,7 +81,7 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
|
||||
|
||||
```c
|
||||
#if defined(ENCODER_MAP_ENABLE)
|
||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
|
||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
|
||||
[_BASE] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
|
||||
[_LOWER] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) },
|
||||
[_RAISE] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) },
|
||||
@ -102,9 +102,9 @@ Using encoder mapping pumps events through the normal QMK keycode processing pip
|
||||
|
||||
## Callbacks
|
||||
|
||||
When not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
|
||||
?> [**Default Behaviour**](https://github.com/qmk/qmk_firmware/blob/master/quantum/encoder.c#L79-#L98): all encoders installed will function as volume up (`KC_VOLU`) on clockwise rotation and volume down (`KC_VOLD`) on counter-clockwise rotation. If you do not wish to override this, no further configuration is necessary.
|
||||
|
||||
?> Those who are adding new keyboard support where encoders are enabled at the keyboard level should include basic encoder functionality at the keyboard level (`<keyboard>.c`) using the `encoder_update_kb()` function, that way it works for QMK Configuator users and exists in general.
|
||||
If you would like the alter the default behaviour, and are not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
bool encoder_update_kb(uint8_t index, bool clockwise) {
|
||||
@ -113,9 +113,9 @@ bool encoder_update_kb(uint8_t index, bool clockwise) {
|
||||
}
|
||||
if (index == 0) { /* First encoder */
|
||||
if (clockwise) {
|
||||
tap_code_delay(KC_VOLU, 10);
|
||||
tap_code(KC_PGDN);
|
||||
} else {
|
||||
tap_code_delay(KC_VOLD, 10);
|
||||
tap_code(KC_PGUP);
|
||||
}
|
||||
} else if (index == 1) { /* Second encoder */
|
||||
if (clockwise) {
|
||||
@ -134,9 +134,9 @@ or `keymap.c`:
|
||||
bool encoder_update_user(uint8_t index, bool clockwise) {
|
||||
if (index == 0) { /* First encoder */
|
||||
if (clockwise) {
|
||||
tap_code_delay(KC_VOLU, 10);
|
||||
tap_code(KC_PGDN);
|
||||
} else {
|
||||
tap_code_delay(KC_VOLD, 10);
|
||||
tap_code(KC_PGUP);
|
||||
}
|
||||
} else if (index == 1) { /* Second encoder */
|
||||
if (clockwise) {
|
||||
@ -149,7 +149,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
|
||||
}
|
||||
```
|
||||
|
||||
!> If you return `true` in the keymap level `_user` function, it will allow the keyboard level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
|
||||
!> If you return `true` in the keymap level `_user` function, it will allow the keyboard/core level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
|
||||
|
||||
## Hardware
|
||||
|
||||
|
@ -4,11 +4,12 @@
|
||||
|
||||
The following options are currently available for haptic feedback in `rules.mk`:
|
||||
|
||||
```
|
||||
```make
|
||||
HAPTIC_ENABLE = yes
|
||||
|
||||
HAPTIC_DRIVER += DRV2605L
|
||||
HAPTIC_DRIVER += SOLENOID
|
||||
HAPTIC_DRIVER = drv2605l
|
||||
# or
|
||||
HAPTIC_DRIVER = solenoid
|
||||
```
|
||||
|
||||
The following `config.h` settings are available for all types of haptic feedback:
|
||||
@ -92,30 +93,30 @@ This driver supports 2 different feedback motors. Set the following in your `con
|
||||
|
||||
Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.
|
||||
|
||||
```
|
||||
#define FB_ERM_LRA 0
|
||||
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
||||
#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
||||
```c
|
||||
#define DRV2605L_FB_ERM_LRA 0
|
||||
#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
||||
#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
||||
|
||||
/* Please refer to your datasheet for the optimal setting for your specific motor. */
|
||||
#define RATED_VOLTAGE 3
|
||||
#define V_PEAK 5
|
||||
#define DRV2605L_RATED_VOLTAGE 3
|
||||
#define DRV2605L_V_PEAK 5
|
||||
```
|
||||
##### LRA
|
||||
|
||||
Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.
|
||||
|
||||
```
|
||||
#define FB_ERM_LRA 1
|
||||
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
||||
#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
||||
```c
|
||||
#define DRV2605L_FB_ERM_LRA 1
|
||||
#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
||||
#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
||||
|
||||
/* Please refer to your datasheet for the optimal setting for your specific motor. */
|
||||
#define RATED_VOLTAGE 2
|
||||
#define V_PEAK 2.8
|
||||
#define V_RMS 2.0
|
||||
#define V_PEAK 2.1
|
||||
#define F_LRA 205 /* resonance freq */
|
||||
#define DRV2605L_RATED_VOLTAGE 2
|
||||
#define DRV2605L_V_PEAK 2.8
|
||||
#define DRV2605L_V_RMS 2.0
|
||||
#define DRV2605L_V_PEAK 2.1
|
||||
#define DRV2605L_F_LRA 205 /* resonance freq */
|
||||
```
|
||||
|
||||
#### DRV2605L waveform library
|
||||
@ -170,13 +171,13 @@ List of waveform sequences from the datasheet:
|
||||
| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
|
||||
### Optional DRV2605L defines
|
||||
|
||||
```
|
||||
#define DRV_GREETING *sequence name or number*
|
||||
```c
|
||||
#define DRV2605L_GREETING *sequence name or number*
|
||||
```
|
||||
If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
|
||||
|
||||
```
|
||||
#define DRV_MODE_DEFAULT *sequence name or number*
|
||||
```c
|
||||
#define DRV2605L_DEFAULT_MODE *sequence name or number*
|
||||
```
|
||||
This will set what sequence `HF_RST` will set as the active mode. If not defined, mode will be set to 1 when `HF_RST` is pressed.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# HD44780 LCD Driver
|
||||
# HD44780 LCD Driver :id=hd44780-lcd-driver
|
||||
|
||||
## Supported Hardware
|
||||
## Supported Hardware :id=supported-hardware
|
||||
|
||||
LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) IC or equivalent, communicating in 4-bit mode.
|
||||
|
||||
@ -11,7 +11,7 @@ LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
|
||||
|
||||
To run these modules at 3.3V, an additional MAX660 voltage converter IC must be soldered on, along with two 10µF capacitors. See [this page](https://www.codrey.com/electronic-circuits/hack-your-16x2-lcd/) for more details.
|
||||
|
||||
## Usage
|
||||
## Usage :id=usage
|
||||
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
@ -19,7 +19,7 @@ Add the following to your `rules.mk`:
|
||||
HD44780_ENABLE = yes
|
||||
```
|
||||
|
||||
## Basic Configuration
|
||||
## Basic Configuration :id=basic-configuration
|
||||
|
||||
Add the following to your `config.h`:
|
||||
|
||||
@ -33,9 +33,9 @@ Add the following to your `config.h`:
|
||||
|`HD44780_DISPLAY_LINES`|`2` |The number of visible lines on the display |
|
||||
|`HD44780_WRAP_LINES` |*Not defined* |If defined, input characters will wrap to the next line |
|
||||
|
||||
## Examples
|
||||
## Examples :id=examples
|
||||
|
||||
### Hello World
|
||||
### Hello World :id=example-hello-world
|
||||
|
||||
Add the following to your `keymap.c`:
|
||||
|
||||
@ -46,7 +46,7 @@ void keyboard_post_init_user(void) {
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Character Definition
|
||||
### Custom Character Definition :id=example-custom-character
|
||||
|
||||
Up to eight custom characters can be defined. This data is stored in the Character Generator RAM (CGRAM), and is not persistent across power cycles.
|
||||
|
||||
@ -77,15 +77,15 @@ void keyboard_post_init_user(void) {
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
## API :id=api
|
||||
|
||||
### `void hd44780_init(bool cursor, bool blink)`
|
||||
### `void hd44780_init(bool cursor, bool blink)` :id=api-hd44780-init
|
||||
|
||||
Initialize the display.
|
||||
|
||||
This function should be called only once, before any of the other functions can be called.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-init-arguments
|
||||
|
||||
- `bool cursor`
|
||||
Whether to show the cursor.
|
||||
@ -94,7 +94,7 @@ This function should be called only once, before any of the other functions can
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_clear(void)`
|
||||
### `void hd44780_clear(void)` :id=api-hd44780-clear
|
||||
|
||||
Clear the display.
|
||||
|
||||
@ -102,7 +102,7 @@ This function is called on init.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_home(void)`
|
||||
### `void hd44780_home(void)` :id=api-hd44780-home
|
||||
|
||||
Move the cursor to the home position.
|
||||
|
||||
@ -110,13 +110,13 @@ This function is called on init.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_on(bool cursor, bool blink)`
|
||||
### `void hd44780_on(bool cursor, bool blink)` :id=api-hd44780-on
|
||||
|
||||
Turn the display on, and/or set the cursor properties.
|
||||
|
||||
This function is called on init.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-on-arguments
|
||||
|
||||
- `bool cursor`
|
||||
Whether to show the cursor.
|
||||
@ -125,17 +125,17 @@ This function is called on init.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_off(void)`
|
||||
### `void hd44780_off(void)` :id=api-hd44780-off
|
||||
|
||||
Turn the display off.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_set_cursor(uint8_t col, uint8_t line)`
|
||||
### `void hd44780_set_cursor(uint8_t col, uint8_t line)` :id=api-hd44780-set-cursor
|
||||
|
||||
Move the cursor to the specified position on the display.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-set-cursor-arguments
|
||||
|
||||
- `uint8_t col`
|
||||
The column number to move to, from 0 to 15 on 16x2 displays.
|
||||
@ -144,48 +144,48 @@ Move the cursor to the specified position on the display.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_putc(char c)`
|
||||
### `void hd44780_putc(char c)` :id=api-hd44780-putc
|
||||
|
||||
Print a character to the display. The newline character `\n` will move the cursor to the start of the next line.
|
||||
|
||||
The exact character shown may depend on the ROM code of your particular display - refer to the datasheet for the full character set.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-putc-arguments
|
||||
|
||||
- `char c`
|
||||
The character to print.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_puts(const char *s)`
|
||||
### `void hd44780_puts(const char *s)` :id=api-hd44780-puts
|
||||
|
||||
Print a string of characters to the display.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-puts-arguments
|
||||
|
||||
- `const char *s`
|
||||
The string to print.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_puts_P(const char *s)`
|
||||
### `void hd44780_puts_P(const char *s)` :id=api-hd44780-puts-p
|
||||
|
||||
Print a string of characters from PROGMEM to the display.
|
||||
|
||||
On ARM devices, this function is simply an alias of `hd44780_puts()`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-puts-p-arguments
|
||||
|
||||
- `const char *s`
|
||||
The PROGMEM string to print (ie. `PSTR("Hello")`).
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_define_char(uint8_t index, uint8_t *data)`
|
||||
### `void hd44780_define_char(uint8_t index, uint8_t *data)` :id=api-hd44780-define-char
|
||||
|
||||
Define a custom character.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-define-char-arguments
|
||||
|
||||
- `uint8_t index`
|
||||
The index of the custom character to define, from 0 to 7.
|
||||
@ -194,13 +194,13 @@ Define a custom character.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)`
|
||||
### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)` :id=api-hd44780-define-char-p
|
||||
|
||||
Define a custom character from PROGMEM.
|
||||
|
||||
On ARM devices, this function is simply an alias of `hd44780_define_char()`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-define-char-p-arguments
|
||||
|
||||
- `uint8_t index`
|
||||
The index of the custom character to define, from 0 to 7.
|
||||
@ -209,21 +209,21 @@ On ARM devices, this function is simply an alias of `hd44780_define_char()`.
|
||||
|
||||
---
|
||||
|
||||
### `bool hd44780_busy(void)`
|
||||
### `bool hd44780_busy(void)` :id=api-hd44780-busy
|
||||
|
||||
Indicates whether the display is currently processing, and cannot accept instructions.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-hd44780-busy-arguments
|
||||
|
||||
`true` if the display is busy.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_write(uint8_t data, bool isData)`
|
||||
### `void hd44780_write(uint8_t data, bool isData)` :id=api-hd44780-write
|
||||
|
||||
Write a byte to the display.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-write-arguments
|
||||
|
||||
- `uint8_t data`
|
||||
The byte to send to the display.
|
||||
@ -232,67 +232,67 @@ Write a byte to the display.
|
||||
|
||||
---
|
||||
|
||||
### `uint8_t hd44780_read(bool isData)`
|
||||
### `uint8_t hd44780_read(bool isData)` :id=api-hd44780-read
|
||||
|
||||
Read a byte from the display.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-read-arguments
|
||||
|
||||
- `bool isData`
|
||||
Whether to read the current cursor position, or the character at the cursor.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-hd44780-read-return
|
||||
|
||||
If `isData` is `true`, the returned byte will be the character at the current DDRAM address. Otherwise, it will be the current DDRAM address and the busy flag.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_command(uint8_t command)`
|
||||
### `void hd44780_command(uint8_t command)` :id=api-hd44780-command
|
||||
|
||||
Send a command to the display. Refer to the datasheet and `hd44780.h` for the valid commands and defines.
|
||||
|
||||
This function waits for the display to clear the busy flag before sending the command.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-command-arguments
|
||||
|
||||
- `uint8_t command`
|
||||
The command to send.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_data(uint8_t data)`
|
||||
### `void hd44780_data(uint8_t data)` :id=api-hd44780-data
|
||||
|
||||
Send a byte of data to the display.
|
||||
|
||||
This function waits for the display to clear the busy flag before sending the data.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-data-arguments
|
||||
|
||||
- `uint8_t data`
|
||||
The byte of data to send.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_set_cgram_address(uint8_t address)`
|
||||
### `void hd44780_set_cgram_address(uint8_t address)` :id=api-hd44780-set-cgram-address
|
||||
|
||||
Set the CGRAM address.
|
||||
|
||||
This function is used when defining custom characters.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-set-cgram-address-arguments
|
||||
|
||||
- `uint8_t address`
|
||||
The CGRAM address to move to, from `0x00` to `0x3F`.
|
||||
|
||||
---
|
||||
|
||||
### `void hd44780_set_ddram_address(uint8_t address)`
|
||||
### `void hd44780_set_ddram_address(uint8_t address)` :id=api-hd44780-set-ddram-address
|
||||
|
||||
Set the DDRAM address.
|
||||
|
||||
This function is used when printing characters to the display, and setting the cursor.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-hd44780-set-ddram-address-arguments
|
||||
|
||||
- `uint8_t address`
|
||||
The DDRAM address to move to, from `0x00` to `0x7F`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Key Overrides
|
||||
# Key Overrides :id=key-overrides
|
||||
|
||||
Key overrides allow you to override modifier-key combinations to send a different modifier-key combination or perform completely custom actions. Don't want `shift` + `1` to type `!` on your computer? Use a key override to make your keyboard type something different when you press `shift` + `1`. The general behavior is like this: If `modifiers w` + `key x` are pressed, replace these keys with `modifiers y` + `key z` in the keyboard report.
|
||||
|
||||
@ -10,13 +10,13 @@ You can use key overrides in a similar way to momentary layer/fn keys to activat
|
||||
- Create custom shortcuts or change existing ones: E.g. Send `ctrl`+`shift`+`z` when `ctrl`+`y` is pressed.
|
||||
- Run custom code when `ctrl` + `alt` + `esc` is pressed.
|
||||
|
||||
## Setup
|
||||
## Setup :id=setup
|
||||
|
||||
To enable this feature, you need to add `KEY_OVERRIDE_ENABLE = yes` to your `rules.mk`.
|
||||
|
||||
Then, in your `keymap.c` file, you'll need to define the array `key_overrides`, which defines all key overrides to be used. Each override is a value of type `key_override_t`. The array `key_overrides` is `NULL`-terminated and contains pointers to `key_override_t` values (`const key_override_t **`).
|
||||
|
||||
## Creating Key Overrides
|
||||
## Creating Key Overrides :id=creating-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:
|
||||
|
||||
@ -34,7 +34,7 @@ Additionally takes a bitmask `options` that specifies additional options. See `k
|
||||
|
||||
For more customization possibilities, you may directly create a `key_override_t`, which allows you to customize even more behavior. Read further below for details and examples.
|
||||
|
||||
## Simple Example
|
||||
## Simple Example :id=simple-example
|
||||
|
||||
This shows how the mentioned example of sending `delete` when `shift` + `backspace` are pressed is realized:
|
||||
|
||||
@ -48,9 +48,9 @@ const key_override_t **key_overrides = (const key_override_t *[]){
|
||||
};
|
||||
```
|
||||
|
||||
## Intermediate Difficulty Examples
|
||||
## Intermediate Difficulty Examples :id=intermediate-difficulty-examples
|
||||
|
||||
### Media Controls & Screen Brightness
|
||||
### Media Controls & Screen Brightness :id=media-controls-amp-screen-brightness
|
||||
|
||||
In this example a single key is configured to control media, volume and screen brightness by using key overrides.
|
||||
|
||||
@ -102,7 +102,7 @@ const key_override_t **key_overrides = (const key_override_t *[]){
|
||||
};
|
||||
```
|
||||
|
||||
### Flexible macOS-friendly Grave Escape
|
||||
### Flexible macOS-friendly Grave Escape :id=flexible-macos-friendly-grave-escape
|
||||
The [Grave Escape feature](feature_grave_esc.md) is limited in its configurability and has [bugs when used on macOS](feature_grave_esc.md#caveats). Key overrides can be used to achieve a similar functionality as Grave Escape, but with more customization and without bugs on macOS.
|
||||
|
||||
```c
|
||||
@ -121,8 +121,8 @@ const key_override_t **key_overrides = (const key_override_t *[]){
|
||||
|
||||
In addition to not encountering unexpected bugs on macOS, you can also change the behavior as you wish. Instead setting `GUI` + `ESC` = `` ` `` you may change it to an arbitrary other modifier, for example `Ctrl` + `ESC` = `` ` ``.
|
||||
|
||||
## Advanced Examples
|
||||
### Modifiers as Layer Keys
|
||||
## Advanced Examples :id=advanced-examples
|
||||
### Modifiers as Layer Keys :id=modifiers-as-layer-keys
|
||||
|
||||
Do you really need a dedicated key to toggle your fn layer? With key overrides, perhaps not. This example shows how you can configure to use `rGUI` + `rAlt` (right GUI and right alt) to access a momentary layer like an fn layer. With this you completely eliminate the need to use a dedicated layer key. Of course the choice of modifier keys can be changed as needed, `rGUI` + `rAlt` is just an example here.
|
||||
|
||||
@ -150,7 +150,7 @@ const key_override_t fn_override = {.trigger_mods = MOD_BIT(KC_RGUI) |
|
||||
.enabled = NULL};
|
||||
```
|
||||
|
||||
## Keycodes
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
|Keycode |Aliases |Description |
|
||||
|------------------------|---------|----------------------|
|
||||
@ -158,7 +158,7 @@ const key_override_t fn_override = {.trigger_mods = MOD_BIT(KC_RGUI) |
|
||||
|`QK_KEY_OVERRIDE_ON` |`KO_ON` |Turn on key overrides |
|
||||
|`QK_KEY_OVERRIDE_OFF` |`KO_OFF` |Turn off key overrides|
|
||||
|
||||
## Reference for `key_override_t`
|
||||
## Reference for `key_override_t` :id=reference-for-key_override_t
|
||||
|
||||
Advanced users may need more customization than what is offered by the simple `ko_make` initializers. For this, directly create a `key_override_t` value and set all members. Below is a reference for all members of `key_override_t`.
|
||||
|
||||
@ -175,7 +175,7 @@ Advanced users may need more customization than what is offered by the simple `k
|
||||
| `void *context` | A context that will be passed to the custom action function. |
|
||||
| `bool *enabled` | If this points to false this override will not be used. Set to NULL to always have this override enabled. |
|
||||
|
||||
### Reference for `ko_option_t`
|
||||
## Reference for `ko_option_t` :id=reference-for-ko_option_t
|
||||
|
||||
Bitfield with various options controlling the behavior of a key override.
|
||||
|
||||
@ -189,11 +189,11 @@ Bitfield with various options controlling the behavior of a key override.
|
||||
| `ko_option_no_reregister_trigger` | If set, the trigger key will never be registered again after the override is deactivated. |
|
||||
| `ko_options_default` | The default options used by the `ko_make_xxx` functions |
|
||||
|
||||
## For Advanced Users: Inner Workings
|
||||
## For Advanced Users: Inner Workings :id=for-advanced-users-inner-workings
|
||||
|
||||
This section explains how a key override works in detail, explaining where each member of `key_override_t` comes into play. Understanding this is essential to be able to take full advantage of all the options offered by key overrides.
|
||||
|
||||
#### Activation
|
||||
#### Activation :id=activation
|
||||
|
||||
When the necessary keys are pressed (`trigger_mods` + `trigger`), the override is 'activated' and the replacement key is registered in the keyboard report (`replacement`), while the `trigger` key is removed from the keyboard report. The trigger modifiers may also be removed from the keyboard report upon activation of an override (`suppressed_mods`). The override will not activate if any of the `negative_modifiers` are pressed.
|
||||
|
||||
@ -207,11 +207,11 @@ Use the `option` member to customize which of these events are allowed to activa
|
||||
|
||||
In any case, a key override can only activate if the `trigger` key is the _last_ non-modifier key that was pressed down. This emulates the behavior of how standard OSes (macOS, Windows, Linux) handle normal key input (to understand: Hold down `a`, then also hold down `b`, then hold down `shift`; `B` will be typed but not `A`).
|
||||
|
||||
#### Deactivation
|
||||
#### Deactivation :id=deactivation
|
||||
|
||||
An override is 'deactivated' when one of the trigger keys (`trigger_mods`, `trigger`) is lifted, another non-modifier key is pressed down, or one of the `negative_modifiers` is pressed down. When an override deactivates, the `replacement` key is removed from the keyboard report, while the `suppressed_mods` that are still held down are re-added to the keyboard report. By default, the `trigger` key is re-added to the keyboard report if it is still held down and no other non-modifier key has been pressed since. This again emulates the behavior of how standard OSes handle normal key input (To understand: hold down `a`, then also hold down `b`, then also `shift`, then release `b`; `A` will not be typed even though you are holding the `a` and `shift` keys). Use the `option` field `ko_option_no_reregister_trigger` to prevent re-registering the trigger key in all cases.
|
||||
|
||||
#### Key Repeat Delay
|
||||
#### Key Repeat Delay :id=key-repeat-delay
|
||||
|
||||
A third way in which standard OS-handling of modifier-key input is emulated in key overrides is with a ['key repeat delay'](https://www.dummies.com/computers/pcs/set-your-keyboards-repeat-delay-and-repeat-rate/). To explain what this is, let's look at how normal keyboard input is handled by mainstream OSes again: If you hold down `a`, followed by `shift`, you will see the letter `a` is first typed, then for a short moment nothing is typed and then repeating `A`s are typed. Take note that, although shift is pressed down just after `a` is pressed, it takes a moment until `A` is typed. This is caused by the aforementioned key repeat delay, and it is a feature that prevents unwanted repeated characters from being typed.
|
||||
|
||||
@ -222,6 +222,33 @@ This applies equally to releasing a modifier: When you hold `shift`, then press
|
||||
The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT_DELAY` macro. Define this value in your `config.h` file to change it. It is 500ms by default.
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
@ -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_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_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_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. |
|
||||
@ -127,6 +127,54 @@ layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Keycode to cycle through layers
|
||||
|
||||
This example shows how to implement a custom keycode to cycle through a range of layers.
|
||||
|
||||
```c
|
||||
// Define the keycode, `QK_USER` avoids collisions with existing keycodes
|
||||
enum keycodes {
|
||||
KC_CYCLE_LAYERS = QK_USER,
|
||||
};
|
||||
|
||||
// 1st layer on the cycle
|
||||
#define LAYER_CYCLE_START 0
|
||||
// Last layer on the cycle
|
||||
#define LAYER_CYCLE_END 4
|
||||
|
||||
// Add the behaviour of this new keycode
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case KC_CYCLE_LAYERS:
|
||||
// Our logic will happen on presses, nothing is done on releases
|
||||
if (!record->event.pressed) {
|
||||
// We've already handled the keycode (doing nothing), let QMK know so no further code is run unnecessarily
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t current_layer = get_highest_layer(layer_state);
|
||||
|
||||
// Check if we are within the range, if not quit
|
||||
if (current_layer > LAYER_CYCLE_END || current_layer < LAYER_CYCLE_START) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t next_layer = current_layer + 1;
|
||||
if (next_layer > LAYER_CYCLE_END) {
|
||||
next_layer = LAYER_CYCLE_START;
|
||||
}
|
||||
layer_move(next_layer);
|
||||
return false;
|
||||
|
||||
// Process other keycodes normally
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Place `KC_CYCLE_LAYERS` as a keycode in your keymap
|
||||
```
|
||||
|
||||
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
|
||||
|
||||
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
|
||||
|
@ -12,7 +12,7 @@ There is basic support for addressable LED matrix lighting with the I2C IS31FL37
|
||||
|
||||
```make
|
||||
LED_MATRIX_ENABLE = yes
|
||||
LED_MATRIX_DRIVER = IS31FL3731
|
||||
LED_MATRIX_DRIVER = is31fl3731
|
||||
```
|
||||
|
||||
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
|
||||
@ -139,7 +139,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
|
||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
const is31_led __flash g_is31_leds[LED_MATRIX_LED_COUNT] = {
|
||||
const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | LED address
|
||||
@ -158,7 +158,7 @@ Eg `#define ISSI_MANUAL_SCALING 3`
|
||||
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
|
||||
const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
|
||||
* LED Index
|
||||
* | Scaling
|
||||
* | | */
|
||||
@ -247,7 +247,6 @@ enum led_matrix_effects {
|
||||
LED_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom
|
||||
LED_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in
|
||||
LED_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard
|
||||
#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
|
||||
LED_MATRIX_SOLID_REACTIVE_SIMPLE, // Pulses keys hit then fades out
|
||||
LED_MATRIX_SOLID_REACTIVE_WIDE // Value pulses near a single key hit then fades out
|
||||
LED_MATRIX_SOLID_REACTIVE_MULTIWIDE // Value pulses near multiple key hits then fades out
|
||||
@ -257,7 +256,6 @@ enum led_matrix_effects {
|
||||
LED_MATRIX_SOLID_REACTIVE_MULTINEXUS // Value pulses away on the same column and row of multiple key hits then fades out
|
||||
LED_MATRIX_SOLID_SPLASH, // Value pulses away from a single key hit then fades out
|
||||
LED_MATRIX_SOLID_MULTISPLASH, // Value pulses away from multiple key hits then fades out
|
||||
#endif
|
||||
LED_MATRIX_WAVE_LEFT_RIGHT // Sine wave scrolling from left to right
|
||||
LED_MATRIX_WAVE_UP_DOWN // Sine wave scrolling from up to down
|
||||
LED_MATRIX_EFFECT_MAX
|
||||
@ -281,8 +279,6 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|
||||
|`#define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT` |Enables `LED_MATRIX_WAVE_LEFT_RIGHT` |
|
||||
|`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` |
|
||||
|
||||
?> These modes don't require any additional defines.
|
||||
|
||||
|Reactive Defines |Description |
|
||||
|-------------------------------------------------------|----------------------------------------------|
|
||||
|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
|
||||
@ -295,7 +291,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|
||||
|`#define ENABLE_LED_MATRIX_SOLID_SPLASH` |Enables `LED_MATRIX_SOLID_SPLASH` |
|
||||
|`#define ENABLE_LED_MATRIX_SOLID_MULTISPLASH` |Enables `LED_MATRIX_SOLID_MULTISPLASH` |
|
||||
|
||||
?> These modes also require the `LED_MATRIX_KEYPRESSES` or `LED_MATRIX_KEYRELEASES` define to be available.
|
||||
?> These modes introduce additional logic that can increase firmware size.
|
||||
|
||||
## Custom LED Matrix Effects :id=custom-led-matrix-effects
|
||||
|
||||
@ -361,9 +357,7 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
|
||||
## Additional `config.h` Options :id=additional-configh-options
|
||||
|
||||
```c
|
||||
#define LED_MATRIX_KEYPRESSES // reacts to keypresses
|
||||
#define LED_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
|
||||
#define LED_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
|
||||
#define LED_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
|
||||
#define LED_MATRIX_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off
|
||||
#define LED_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
|
||||
#define LED_MATRIX_LED_PROCESS_LIMIT (LED_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
|
||||
@ -373,18 +367,12 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
|
||||
#define LED_MATRIX_DEFAULT_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
|
||||
#define LED_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
|
||||
#define LED_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
|
||||
// If LED_MATRIX_KEYPRESSES or LED_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
|
||||
// If reactive effects are enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
|
||||
```
|
||||
|
||||
## EEPROM storage :id=eeprom-storage
|
||||
|
||||
The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
|
||||
|
||||
```c
|
||||
#define EECONFIG_LED_MATRIX (uint32_t *)28
|
||||
```
|
||||
|
||||
Where `28` is an unused index from `eeconfig.h`.
|
||||
The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time).
|
||||
|
||||
### Direct Operation :id=direct-operation
|
||||
|Function |Description |
|
||||
@ -439,7 +427,7 @@ Where `28` is an unused index from `eeconfig.h`.
|
||||
|
||||
### 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
|
||||
bool led_matrix_indicators_kb(void) {
|
||||
if (!led_matrix_indicators_user()) {
|
||||
|
@ -27,7 +27,7 @@ You can define up to 32 macros in a `keymap.json` file, as used by [Configurator
|
||||
],
|
||||
[
|
||||
{"action":"tap", "keycodes": ["F1"]},
|
||||
{"action":"delay", "duration": "1000"},
|
||||
{"action":"delay", "duration": 1000},
|
||||
{"action":"tap", "keycodes": ["PGDN"]}
|
||||
]
|
||||
],
|
||||
|
@ -67,6 +67,7 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|
||||
|`MOUSEKEY_TIME_TO_MAX` |30 |Time until maximum cursor speed is reached |
|
||||
|`MOUSEKEY_WHEEL_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
|
||||
|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements |
|
||||
|`MOUSEKEY_WHEEL_DELTA` |1 |Wheel movement step size |
|
||||
|`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|
||||
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached |
|
||||
|
||||
@ -101,7 +102,7 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
|
||||
Tips:
|
||||
|
||||
* The smoothness of the cursor movement depends on the `MOUSEKEY_INTERVAL` setting. The shorter the interval is set the smoother the movement will be. Setting the value too low makes the cursor unresponsive. Lower settings are possible if the micro processor is fast enough. For example: At an interval of `8` milliseconds, `125` movements per second will be initiated. With a base speed of `1000` each movement will move the cursor by `8` pixels.
|
||||
* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `2`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
|
||||
* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
|
||||
|
||||
### Constant mode
|
||||
|
||||
|
@ -2,15 +2,19 @@
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
OLED modules using SSD1306 or SH1106 driver ICs, communicating over I2C.
|
||||
OLED modules using SSD1306, SH1106 or SH1107 driver ICs, communicating over I2C or SPI.
|
||||
Tested combinations:
|
||||
|
||||
|IC |Size |Platform|Notes |
|
||||
|---------|------|--------|------------------------|
|
||||
|SSD1306 |128x32|AVR |Primary support |
|
||||
|SSD1306 |128x64|AVR |Verified working |
|
||||
|SSD1306 |128x32|Arm | |
|
||||
|SH1106 |128x64|AVR |No rotation or scrolling|
|
||||
|IC |Size |Platform|Notes |
|
||||
|---------|-------|--------|------------------------|
|
||||
|SSD1306 |128x32 |AVR |Primary support |
|
||||
|SSD1306 |128x64 |AVR |Verified working |
|
||||
|SSD1306 |128x32 |Arm | |
|
||||
|SSD1306 |128x64 |Arm |Verified working |
|
||||
|SH1106 |128x64 |AVR |No scrolling |
|
||||
|SH1107 |64x128 |AVR |No scrolling |
|
||||
|SH1107 |64x128 |Arm |No scrolling |
|
||||
|SH1107 |128x128|Arm |No scrolling |
|
||||
|
||||
Hardware configurations using Arm-based microcontrollers or different sizes of OLED modules may be compatible, but are untested.
|
||||
|
||||
@ -23,13 +27,24 @@ OLED_ENABLE = yes
|
||||
```
|
||||
|
||||
## OLED type
|
||||
|OLED Driver |Supported Device |
|
||||
|-------------------|---------------------------|
|
||||
|SSD1306 (default) |For both SSD1306 and SH1106|
|
||||
|
||||
|OLED Driver |Supported Device |
|
||||
|-------------------|------------------------------------|
|
||||
|`ssd1306` (default)|For both SSD1306, SH1106, and SH1107|
|
||||
|
||||
e.g.
|
||||
```make
|
||||
OLED_DRIVER = SSD1306
|
||||
OLED_DRIVER = ssd1306
|
||||
```
|
||||
|
||||
|OLED Transport | |
|
||||
|---------------|------------------------------------------------|
|
||||
|`i2c` (default)| Uses I2C for communication with the OLED panel |
|
||||
|`spi` | Uses SPI for communication with the OLED panel |
|
||||
|
||||
e.g.
|
||||
```make
|
||||
OLED_TRANSPORT = i2c
|
||||
```
|
||||
|
||||
Then in your `keymap.c` file, implement the OLED task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
|
||||
@ -159,32 +174,57 @@ These configuration options should be placed in `config.h`. Example:
|
||||
#define OLED_BRIGHTNESS 128
|
||||
```
|
||||
|
||||
|Define |Default |Description |
|
||||
|---------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
|
||||
|`OLED_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC. |
|
||||
|`OLED_DISPLAY_CLOCK` |`0x80` |Set the display clock divide ratio/oscillator frequency. |
|
||||
|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
|
||||
|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
|
||||
|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
|
||||
|`OLED_FONT_WIDTH` |`6` |The font width |
|
||||
|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
|
||||
|`OLED_IC` |`OLED_IC_SSD1306` |Set to `OLED_IC_SH1106` or `OLED_IC_SH1107` if the corresponding controller chip is used. |
|
||||
|`OLED_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
|
||||
|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
|
||||
|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|
||||
|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
|
||||
|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|
||||
|`OLED_UPDATE_INTERVAL` |`0` (`50` for split keyboards) |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
|
||||
|`OLED_UPDATE_PROCESS_LIMIT'|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
|
||||
|
||||
### I2C Configuration
|
||||
|Define |Default |Description |
|
||||
|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DISPLAY_ADDRESS` |`0x3C` |The i2c address of the OLED Display |
|
||||
|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
|
||||
|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
|
||||
|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
|
||||
|`OLED_FONT_WIDTH` |`6` |The font width |
|
||||
|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
|
||||
|`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_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
|
||||
|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
|
||||
|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|
||||
|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
|
||||
|`OLED_IC` |`OLED_IC_SSD1306`|Set to `OLED_IC_SH1106` if you're using the SH1106 OLED controller. |
|
||||
|`OLED_COLUMN_OFFSET` |`0` |(SH1106 only.) Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC.|
|
||||
|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
|
||||
|`OLED_UPDATE_INTERVAL` |`0` |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
|
||||
|
||||
## 128x64 & Custom sized OLED Displays
|
||||
### SPI Configuration
|
||||
|
||||
The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind. We have added a define, `OLED_DISPLAY_128X64`, to switch all the values to be used in a 128x64 display, as well as added a custom define, `OLED_DISPLAY_CUSTOM`, that allows you to provide the necessary values to the driver.
|
||||
|Define |Default |Description |
|
||||
|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DC_PIN` | Required |The pin used for the DC connection of the OLED Display. |
|
||||
|`OLED_CS_PIN` | Required |The pin used for the CS connection of the OLED Display. |
|
||||
|`OLED_RST_PIN` | *Not defined* |The pin used for the RST connection of the OLED Display (may be left undefined if the RST pin is not connected). |
|
||||
|`OLED_SPI_MODE` |`3` (default) |The SPI Mode for the OLED Display (not typically changed). |
|
||||
|`OLED_SPI_DIVISOR` |`2` (default) |The SPI Multiplier to use for the OLED Display. |
|
||||
|
||||
## 128x64 & Custom sized OLED Displays
|
||||
|
||||
The default display size for this feature is 128x32, and the defaults are set with that in mind. However, there are a number of additional presets for common sizes that we have added. You can define one of these values to use the presets. If your display doesn't match one of these presets, you can define `OLED_DISPLAY_CUSTOM` to manually specify all of the values.
|
||||
|
||||
|Define |Default |Description |
|
||||
|----------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DISPLAY_128X64` |*Not defined* |Changes the display defines for use with 128x64 displays. |
|
||||
|`OLED_DISPLAY_64X32` |*Not defined* |Changes the display defines for use with 64x32 displays. |
|
||||
|`OLED_DISPLAY_64X48` |*Not defined* |Changes the display defines for use with 64x48 displays. |
|
||||
|`OLED_DISPLAY_64X128` |*Not defined* |Changes the display defines for use with 64x128 displays. |
|
||||
|`OLED_DISPLAY_128X128`|*Not defined* |Changes the display defines for use with 128x128 displays. |
|
||||
|`OLED_DISPLAY_CUSTOM` |*Not defined* |Changes the display defines for use with custom displays.<br>Requires user to implement the below defines. |
|
||||
|
||||
!> 64x128 and 128x128 displays default to the SH1107 IC type, as these heights are not supported by the other IC types.
|
||||
|
||||
|Define |Default |Description |
|
||||
|---------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DISPLAY_128X64`|*Not defined* |Changes the display defines for use with 128x64 displays. |
|
||||
|`OLED_DISPLAY_CUSTOM`|*Not defined* |Changes the display defines for use with custom displays.<br>Requires user to implement the below defines. |
|
||||
| --------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DISPLAY_WIDTH` |`128` |The width of the OLED display. |
|
||||
|`OLED_DISPLAY_HEIGHT`|`32` |The height of the OLED display. |
|
||||
|`OLED_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br>`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`. |
|
||||
@ -192,14 +232,13 @@ These configuration options should be placed in `config.h`. Example:
|
||||
|`OLED_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br>`(sizeof(OLED_BLOCK_TYPE) * 8)`. |
|
||||
|`OLED_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br>`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`. |
|
||||
|`OLED_COM_PINS` |`COM_PINS_SEQ` |How the SSD1306 chip maps it's memory to display.<br>Options are `COM_PINS_SEQ`, `COM_PINS_ALT`, `COM_PINS_SEQ_LR`, & `COM_PINS_ALT_LR`.|
|
||||
|`OLED_COM_PIN_COUNT` |*Not defined* |Number of COM pins supported by the controller.<br>If not defined, the value appropriate for the defined `OLED_IC` is used. |
|
||||
|`OLED_COM_PIN_OFFSET`|`0` |Number of the first COM pin used by the OLED matrix. |
|
||||
|`OLED_SOURCE_MAP` |`{ 0, ... N }` |Precalculated source array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
|
||||
|`OLED_TARGET_MAP` |`{ 24, ... N }`|Precalculated target array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
|
||||
|
||||
|
||||
### 90 Degree Rotation - Technical Mumbo Jumbo
|
||||
|
||||
!> Rotation is unsupported on the SH1106.
|
||||
|
||||
```c
|
||||
// OLED Rotation enum values are flags
|
||||
typedef enum {
|
||||
@ -210,7 +249,7 @@ typedef enum {
|
||||
} oled_rotation_t;
|
||||
```
|
||||
|
||||
OLED displays driven by SSD1306 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
|
||||
OLED displays driven by SSD1306, SH1106 or SH1107 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
|
||||
|
||||
90 degree rotation is achieved by using bitwise operations to rotate each 8 block of memory and uses two precalculated arrays to remap buffer memory to OLED memory. The memory map defines are precalculated for remap performance and are calculated based on the display height, width, and block size. For example, in the 128x32 implementation with a `uint8_t` block type, we have a 64 byte block size. This gives us eight 8 byte blocks that need to be rotated and rendered. The OLED renders horizontally two 8 byte blocks before moving down a page, e.g:
|
||||
|
||||
@ -232,6 +271,8 @@ However the local buffer is stored as if it was Height x Width display instead o
|
||||
|
||||
So those precalculated arrays just index the memory offsets in the order in which each one iterates its data.
|
||||
|
||||
Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, because these controllers do not support the “horizontal addressing mode”, which allows transferring the data for the whole rotated block at once; instead, separate address setup commands for every page in the block are required. The screen refresh time for SH1107 is therefore about 45% higher than for a same size screen with SSD1306 when using STM32 MCUs (on AVR the slowdown is about 20%, because the code which actually rotates the bitmap consumes more time).
|
||||
|
||||
## OLED API
|
||||
|
||||
```c
|
||||
@ -253,6 +294,11 @@ bool oled_init(oled_rotation_t rotation);
|
||||
oled_rotation_t oled_init_kb(oled_rotation_t rotation);
|
||||
oled_rotation_t oled_init_user(oled_rotation_t rotation);
|
||||
|
||||
// Send commands/data to screen
|
||||
bool oled_send_cmd(const uint8_t *data, uint16_t size);
|
||||
bool oled_send_cmd_P(const uint8_t *data, uint16_t size);
|
||||
bool oled_send_data(const uint8_t *data, uint16_t size);
|
||||
|
||||
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
|
||||
void oled_clear(void);
|
||||
|
||||
@ -353,7 +399,7 @@ void oled_scroll_set_area(uint8_t start_line, uint8_t end_line);
|
||||
// Sets scroll speed, 0-7, fastest to slowest. Default is three.
|
||||
// Does not take effect until scrolling is either started or restarted
|
||||
// the ssd1306 supports 8 speeds with the delay
|
||||
// listed below betwen each frame of the scrolling effect
|
||||
// listed below between each frame of the scrolling effect
|
||||
// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
|
||||
void oled_scroll_set_speed(uint8_t speed);
|
||||
|
||||
@ -386,7 +432,9 @@ uint8_t oled_max_chars(void);
|
||||
uint8_t oled_max_lines(void);
|
||||
```
|
||||
|
||||
!> Scrolling and rotation are unsupported on the SH1106.
|
||||
!> Scrolling is unsupported on the SH1106 and SH1107.
|
||||
|
||||
!> Scrolling does not work properly on the SSD1306 if the display width is smaller than 128.
|
||||
|
||||
## SSD1306.h Driver Conversion Guide
|
||||
|
||||
|
@ -20,13 +20,13 @@ To use the ADNS 5050 sensor, add this to your `rules.mk`
|
||||
POINTING_DEVICE_DRIVER = adns5050
|
||||
```
|
||||
|
||||
The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.
|
||||
The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ------------------- | ------------------------------------------------------------------ | -------------------------- |
|
||||
| `ADNS5050_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
|
||||
| `ADNS5050_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
|
||||
| `ADNS5050_CS_PIN` | (Required) The pin connected to the Chip Select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| -------------------- | ------------------------------------------------------------------ | -------------------------- |
|
||||
| `ADNS5050_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
|
||||
| `ADNS5050_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
|
||||
| `ADNS5050_CS_PIN` | (Required) The pin connected to the Chip Select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
|
||||
|
||||
|
||||
|
||||
@ -40,9 +40,9 @@ To use the ADNS 9800 sensor, add this to your `rules.mk`
|
||||
POINTING_DEVICE_DRIVER = adns9800
|
||||
```
|
||||
|
||||
The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.
|
||||
The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| ----------------------- | ---------------------------------------------------------------------- | ------------------------ |
|
||||
| `ADNS9800_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
|
||||
| `ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
|
||||
@ -63,7 +63,7 @@ POINTING_DEVICE_DRIVER = analog_joystick
|
||||
|
||||
The Analog Joystick is an analog (ADC) driven sensor. There are a variety of joysticks that you can use for this.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| --------------------------------- | -------------------------------------------------------------------------- | ------------- |
|
||||
| `ANALOG_JOYSTICK_X_AXIS_PIN` | (Required) The pin used for the vertical/X axis. | _not defined_ |
|
||||
| `ANALOG_JOYSTICK_Y_AXIS_PIN` | (Required) The pin used for the horizontal/Y axis. | _not defined_ |
|
||||
@ -153,7 +153,7 @@ Additionally, `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE` is supported in thi
|
||||
|
||||
#### Relative mode gestures
|
||||
|
||||
| Gesture Setting | Description | Default |
|
||||
| Gesture Setting (`config.h`) | Description | Default |
|
||||
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
||||
| `CIRQUE_PINNACLE_TAP_ENABLE` | (Optional) Enable tap to "left click". Works on both sides of a split keyboard. | _not defined_ |
|
||||
| `CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE` | (Optional) Tap in upper right corner (half of the finger needs to be outside of the trackpad) of the trackpad will result in "right click". `CIRQUE_PINNACLE_TAP_ENABLE` must be enabled. | _not defined_ |
|
||||
@ -172,10 +172,10 @@ POINTING_DEVICE_DRIVER = paw3204
|
||||
|
||||
The paw 3204 sensor uses a serial type protocol for communication, and requires an additional light source.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ------------------ |--------------------------------------------------------------- | -------------------------- |
|
||||
| `PAW3204_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
|
||||
| `PAW3204_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| -------------------- |--------------------------------------------------------------- | -------------------------- |
|
||||
| `PAW3204_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
|
||||
| `PAW3204_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
|
||||
|
||||
The CPI range is 400-1600, with supported values of (400, 500, 600, 800, 1000, 1200 and 1600). Defaults to 1000 CPI.
|
||||
|
||||
@ -189,7 +189,7 @@ POINTING_DEVICE_DRIVER = pimoroni_trackball
|
||||
|
||||
The Pimoroni Trackball module is a I2C based breakout board with an RGB enable trackball.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| ------------------------------------ | ---------------------------------------------------------------------------------- | ------- |
|
||||
| `PIMORONI_TRACKBALL_ADDRESS` | (Required) Sets the I2C Address for the Pimoroni Trackball. | `0x0A` |
|
||||
| `PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackball in milliseconds. | `100` |
|
||||
@ -197,6 +197,24 @@ The Pimoroni Trackball module is a I2C based breakout board with an RGB enable t
|
||||
| `PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` |
|
||||
| `PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
|
||||
|
||||
### PMW3320 Sensor
|
||||
|
||||
To use the PMW3320 sensor, add this to your `rules.mk`
|
||||
|
||||
```make
|
||||
POINTING_DEVICE_DRIVER = pmw3320
|
||||
```
|
||||
|
||||
The PMW3320 sensor uses a serial type protocol for communication, and requires an additional light source (it could work without one, but expect it to be out of service early).
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ------------------- | ------------------------------------------------------------------- | -------------------------- |
|
||||
| `PMW3320_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
|
||||
| `PMW3320_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
|
||||
| `PMW3320_CS_PIN` | (Required) The pin connected to the cable select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
|
||||
|
||||
The CPI range is 500-3500, in increments of 250. Defaults to 1000 CPI.
|
||||
|
||||
### PMW 3360 and PMW 3389 Sensor
|
||||
|
||||
This drivers supports both the PMW 3360 and PMW 3389 sensor as well as multiple sensors of the same type _per_ controller, so 2 can be attached at the same side for split keyboards (or unsplit keyboards).
|
||||
@ -220,7 +238,7 @@ The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.
|
||||
Both PMW 3360 and PMW 3389 are SPI driven optical sensors, that use a built in IR LED for surface tracking.
|
||||
If you have different CS wiring on each half you can use `PMW33XX_CS_PIN_RIGHT` or `PMW33XX_CS_PINS_RIGHT` in combination with `PMW33XX_CS_PIN` or `PMW33XX_CS_PINS` to configure both sides independently. If `_RIGHT` values aren't provided, they default to be the same as the left ones.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------- | ------------------------ |
|
||||
| `PMW33XX_CS_PIN` | (Required) Sets the Chip Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
|
||||
| `PMW33XX_CS_PINS` | (Alternative) Sets the Chip Select pins connected to multiple sensors. | `{PMW33XX_CS_PIN}` |
|
||||
@ -434,6 +452,75 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.
|
||||
|
||||
### Advanced Drag Scroll
|
||||
|
||||
Sometimes, like with the Cirque trackpad, you will run into issues where the scrolling may be too fast.
|
||||
|
||||
Here is a slightly more advanced example of drag scrolling. You will be able to change the scroll speed based on the values in set in `SCROLL_DIVISOR_H` and `SCROLL_DIVISOR_V`. This bit of code is also set up so that instead of toggling the scrolling state with set_scrolling = !set_scrolling, the set_scrolling variable is set directly to record->event.pressed. This way, the drag scrolling will only be active while the DRAG_SCROLL button is held down.
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
DRAG_SCROLL = SAFE_RANGE,
|
||||
};
|
||||
|
||||
bool set_scrolling = false;
|
||||
|
||||
// Modify these values to adjust the scrolling speed
|
||||
#define SCROLL_DIVISOR_H 8.0
|
||||
#define SCROLL_DIVISOR_V 8.0
|
||||
|
||||
// Variables to store accumulated scroll values
|
||||
float scroll_accumulated_h = 0;
|
||||
float scroll_accumulated_v = 0;
|
||||
|
||||
// Function to handle mouse reports and perform drag scrolling
|
||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
|
||||
// Check if drag scrolling is active
|
||||
if (set_scrolling) {
|
||||
// Calculate and accumulate scroll values based on mouse movement and divisors
|
||||
scroll_accumulated_h += (float)mouse_report.x / SCROLL_DIVISOR_H;
|
||||
scroll_accumulated_v += (float)mouse_report.y / SCROLL_DIVISOR_V;
|
||||
|
||||
// Assign integer parts of accumulated scroll values to the mouse report
|
||||
mouse_report.h = (int8_t)scroll_accumulated_h;
|
||||
mouse_report.v = (int8_t)scroll_accumulated_v;
|
||||
|
||||
// Update accumulated scroll values by subtracting the integer parts
|
||||
scroll_accumulated_h -= (int8_t)scroll_accumulated_h;
|
||||
scroll_accumulated_v -= (int8_t)scroll_accumulated_v;
|
||||
|
||||
// Clear the X and Y values of the mouse report
|
||||
mouse_report.x = 0;
|
||||
mouse_report.y = 0;
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
// Function to handle key events and enable/disable drag scrolling
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case DRAG_SCROLL:
|
||||
// Toggle set_scrolling when DRAG_SCROLL key is pressed or released
|
||||
set_scrolling = record->event.pressed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to handle layer changes and disable drag scrolling when not in AUTO_MOUSE_DEFAULT_LAYER
|
||||
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
// Disable set_scrolling if the current layer is not the AUTO_MOUSE_DEFAULT_LAYER
|
||||
if (get_highest_layer(state) != AUTO_MOUSE_DEFAULT_LAYER) {
|
||||
set_scrolling = false;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Split Examples
|
||||
|
||||
The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
|
||||
@ -602,6 +689,10 @@ There are several functions that allow for more advanced interaction with the au
|
||||
| `auto_mouse_layer_off(void)` | Disable target layer if appropriate will call (makes call to `layer_state_set`) | | `void`(None) |
|
||||
| `auto_mouse_toggle(void)` | Toggle on/off target toggle state (disables layer deactivation when true) | | `void`(None) |
|
||||
| `get_auto_mouse_toggle(void)` | Return value of toggling state variable | | `bool` |
|
||||
| `set_auto_mouse_timeout(uint16_t timeout)` | Change/set the timeout for turing off the layer | | `void`(None) |
|
||||
| `get_auto_mouse_timeout(void)` | Return the current timeout for turing off the layer | | `uint16_t` |
|
||||
| `set_auto_mouse_debounce(uint16_t timeout)` | Change/set the debounce for preventing layer activation | | `void`(None) |
|
||||
| `get_auto_mouse_debounce(void)` | Return the current debounce for preventing layer activation | | `uint8_t` |
|
||||
|
||||
_NOTES:_
|
||||
- _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._
|
||||
@ -713,7 +804,7 @@ _Note: The Cirque pinnacle track pad already implements a custom activation func
|
||||
When using a custom pointing device (overwriting `pointing_device_task`) the following code should be somewhere in the `pointing_device_task_*` stack:
|
||||
|
||||
```c
|
||||
void pointing_device_task(void) {
|
||||
bool pointing_device_task(void) {
|
||||
//...Custom pointing device task code
|
||||
|
||||
// handle automatic mouse layer (needs report_mouse_t as input)
|
||||
@ -721,7 +812,7 @@ void pointing_device_task(void) {
|
||||
|
||||
//...More custom pointing device task code
|
||||
|
||||
pointing_device_send();
|
||||
return pointing_device_send();
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Programmable Buttons are keys that have no predefined meaning. This means they can be processed on the host side by custom software without the operating system trying to interpret them.
|
||||
|
||||
The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x07`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`).
|
||||
The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x09`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`).
|
||||
|
||||
?> Currently there is no known support in Windows or macOS. It may be possible to write a custom HID driver to receive these usages, but this is out of the scope of the QMK documentation.
|
||||
|
||||
|
@ -155,6 +155,29 @@ In your keyboard config.h:
|
||||
#endif
|
||||
```
|
||||
|
||||
### RP2040 PIO Version :id=rp2040-pio-version
|
||||
|
||||
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU.
|
||||
|
||||
There are strict requirements for pin ordering but any pair of GPIO pins can be used. The GPIO used for clock must be directly after data, see the included info.json snippet for an example of correct order.
|
||||
|
||||
You may optionally switch the PIO peripheral used with the following define in config.h:
|
||||
```c
|
||||
#define PS2_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the PS2 implementation uses the PIO0 peripheral
|
||||
```
|
||||
|
||||
Example info.json content:
|
||||
|
||||
```json
|
||||
"ps2": {
|
||||
"clock_pin": "GP1",
|
||||
"data_pin": "GP0",
|
||||
"driver": "vendor",
|
||||
"enabled": true,
|
||||
"mouse_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
## Additional Settings :id=additional-settings
|
||||
|
||||
### PS/2 Mouse Features :id=ps2-mouse-features
|
||||
|
@ -1,69 +1,156 @@
|
||||
# Raw HID
|
||||
# Raw HID :id=raw-hid
|
||||
|
||||
Raw HID allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or changing RGB LED colors and modes.
|
||||
The Raw HID feature allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or sending useful metrics like CPU/RAM usage.
|
||||
|
||||
There are two main components to getting raw HID working with your keyboard.
|
||||
In order to communicate with the keyboard using this feature, you will need to write a program that runs on the host. As such, some basic programming skills are required - more if you intend to implement complex behaviour.
|
||||
|
||||
## Keyboard firmware
|
||||
## Usage :id=usage
|
||||
|
||||
The implementation is fairly straightforward for the firmware.
|
||||
In your `rules.mk` add:
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
RAW_ENABLE = yes
|
||||
```
|
||||
|
||||
In your `keymap.c` include `"raw_hid.h"` and implement the following:
|
||||
## Basic Configuration :id=basic-configuration
|
||||
|
||||
By default, the HID Usage Page and Usage ID for the Raw HID interface are `0xFF60` and `0x61`. However, they can be changed if necessary by adding the following to your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|----------------|--------|---------------------------------------|
|
||||
|`RAW_USAGE_PAGE`|`0xFF60`|The usage page of the Raw HID interface|
|
||||
|`RAW_USAGE_ID` |`0x61` |The usage ID of the Raw HID interface |
|
||||
|
||||
## Sending Data to the Keyboard :id=sending-data-to-the-keyboard
|
||||
|
||||
To send data to the keyboard, you must first find a library for communicating with HID devices in the programming language of your choice. Here are some examples:
|
||||
|
||||
* **Node.js:** [node-hid](https://github.com/node-hid/node-hid)
|
||||
* **C/C++:** [hidapi](https://github.com/libusb/hidapi)
|
||||
* **Java:** [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java)
|
||||
* **Python:** [pyhidapi](https://pypi.org/project/hid/)
|
||||
|
||||
Please refer to these libraries' own documentation for instructions on usage. Remember to close the device once you are finished with it!
|
||||
|
||||
Next, you will need to know the USB Vendor and Product IDs of the device. These can easily be found by looking at your keyboard's `info.json`, under the `usb` object (alternatively, you can also use Device Manager on Windows, System Information on macOS, or `lsusb` on Linux). For example, the Vendor ID for the Planck Rev 6 is `0x03A8`, and the Product ID is `0xA4F9`.
|
||||
|
||||
It's also a good idea to narrow down the list of potential HID devices the library may give you by filtering on the usage page and usage ID, to avoid accidentally opening the interface on the same device for the keyboard, or mouse, or media keys, etc.
|
||||
|
||||
Once you are able to open the HID device and send reports to it, it's time to handle them on the keyboard side. Implement the following function in your `keymap.c` and start coding:
|
||||
|
||||
```c
|
||||
void raw_hid_receive(uint8_t *data, uint8_t length) {
|
||||
// Your code goes here. data is the packet received from host.
|
||||
// Your code goes here
|
||||
// `data` is a pointer to the buffer containing the received HID report
|
||||
// `length` is the length of the report - always `RAW_EPSIZE`
|
||||
}
|
||||
```
|
||||
|
||||
The `"raw_hid.h"` header also declares `void raw_hid_send(uint8_t *data, uint8_t length);` which allows sending packets from keyboard to host. As an example, it can also be used for debugging when building your host application by returning all data back to the host.
|
||||
!> Because the HID specification does not support variable length reports, all reports in both directions must be exactly `RAW_EPSIZE` (currently 32) bytes long, regardless of actual payload length. However, variable length payloads can potentially be implemented on top of this by creating your own data structure that may span multiple reports.
|
||||
|
||||
## Receiving Data from the Keyboard :id=receiving-data-from-the-keyboard
|
||||
|
||||
If you need the keyboard to send data back to the host, simply call the `raw_hid_send()` function. It requires two arguments - a pointer to a 32-byte buffer containing the data you wish to send, and the length (which should always be `RAW_EPSIZE`).
|
||||
|
||||
The received report can then be handled in whichever way your HID library provides.
|
||||
|
||||
## Simple Example :id=simple-example
|
||||
|
||||
The following example reads the first byte of the received report from the host, and if it is an ASCII "A", responds with "B". `memset()` is used to fill the response buffer (which could still contain the previous response) with null bytes.
|
||||
|
||||
```c
|
||||
void raw_hid_receive(uint8_t *data, uint8_t length) {
|
||||
raw_hid_send(data, length);
|
||||
uint8_t response[length];
|
||||
memset(response, 0, length);
|
||||
response[0] = 'B';
|
||||
|
||||
if(data[0] == 'A') {
|
||||
raw_hid_send(response, length);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These two functions send and receive packets of length `RAW_EPSIZE` bytes to and from the host (32 on LUFA/ChibiOS/V-USB, 64 on ATSAM).
|
||||
On the host side (here we are using Python and the `pyhidapi` library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent.
|
||||
|
||||
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
|
||||
2. Product ID
|
||||
3. Usage Page
|
||||
4. Usage
|
||||
def get_raw_hid_interface():
|
||||
device_interfaces = hid.enumerate(vendor_id, product_id)
|
||||
raw_hid_interfaces = [i for i in device_interfaces if i['usage_page'] == usage_page and i['usage'] == usage]
|
||||
|
||||
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).
|
||||
* 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/).
|
||||
if interface is None:
|
||||
print("No device found")
|
||||
sys.exit(1)
|
||||
|
||||
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.
|
||||
Unlike Vendor ID and Product ID though, Usage Page and Usage are necessary for successful communication.
|
||||
try:
|
||||
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.
|
||||
|
457
docs/feature_repeat_key.md
Normal file
457
docs/feature_repeat_key.md
Normal file
@ -0,0 +1,457 @@
|
||||
# Repeat Key
|
||||
|
||||
The Repeat Key performs the action of the last pressed key. Tapping the Repeat
|
||||
Key after tapping the <kbd>Z</kbd> key types another "`z`." This is useful for
|
||||
typing doubled letters, like the `z` in "`dazzle`": a double tap on <kbd>Z</kbd>
|
||||
can instead be a roll from <kbd>Z</kbd> to <kbd>Repeat</kbd>, which is
|
||||
potentially faster and more comfortable. The Repeat Key is also useful for
|
||||
hotkeys, like repeating Ctrl + Shift + Right Arrow to select by word.
|
||||
|
||||
Repeat Key remembers mods that were active with the last key press. These mods
|
||||
are combined with any additional mods while pressing the Repeat Key. If the last
|
||||
press key was <kbd>Ctrl</kbd> + <kbd>Z</kbd>, then <kbd>Shift</kbd> +
|
||||
<kbd>Repeat</kbd> performs Ctrl + Shift + `Z`.
|
||||
|
||||
## How do I enable Repeat Key
|
||||
|
||||
In your `rules.mk`, add:
|
||||
|
||||
```make
|
||||
REPEAT_KEY_ENABLE = yes
|
||||
```
|
||||
|
||||
Then pick a key in your keymap and assign it the keycode `QK_REPEAT_KEY` (short
|
||||
alias `QK_REP`). Optionally, use the keycode `QK_ALT_REPEAT_KEY` (short alias
|
||||
`QK_AREP`) on another key.
|
||||
|
||||
## Keycodes
|
||||
|
||||
|Keycode |Aliases |Description |
|
||||
|-----------------------|---------|-------------------------------------|
|
||||
|`QK_REPEAT_KEY` |`QK_REP` |Repeat the last pressed key |
|
||||
|`QK_ALT_REPEAT_KEY` |`QK_AREP`|Perform alternate of the last key |
|
||||
|
||||
## Alternate Repeating
|
||||
|
||||
The Alternate Repeat Key performs the "alternate" action of the last pressed key
|
||||
if it is defined. By default, Alternate Repeat is defined for navigation keys to
|
||||
act in the reverse direction. When the last key is the common "select by word"
|
||||
hotkey Ctrl + Shift + Right Arrow, the Alternate Repeat Key performs Ctrl +
|
||||
Shift + Left Arrow, which together with the Repeat Key enables convenient
|
||||
selection by words in either direction.
|
||||
|
||||
Alternate Repeat is enabled with the Repeat Key by default. Optionally, to
|
||||
reduce firmware size, Alternate Repeat may be disabled by adding in config.h:
|
||||
|
||||
```c
|
||||
#define NO_ALT_REPEAT_KEY
|
||||
```
|
||||
|
||||
The following alternate keys are defined by default. See
|
||||
`get_alt_repeat_key_keycode_user()` below for how to change or add to these
|
||||
definitions. Where it makes sense, these definitions also include combinations
|
||||
with mods, like Ctrl + Left ↔ Ctrl + Right Arrow.
|
||||
|
||||
**Navigation**
|
||||
|
||||
|Keycodes |Description |
|
||||
|-----------------------------------|-----------------------------------|
|
||||
|`KC_LEFT` ↔ `KC_RGHT` | Left ↔ Right Arrow |
|
||||
|`KC_UP` ↔ `KC_DOWN` | Up ↔ Down Arrow |
|
||||
|`KC_HOME` ↔ `KC_END` | Home ↔ End |
|
||||
|`KC_PGUP` ↔ `KC_PGDN` | Page Up ↔ Page Down |
|
||||
|`KC_MS_L` ↔ `KC_MS_R` | Mouse Cursor Left ↔ Right |
|
||||
|`KC_MS_U` ↔ `KC_MS_D` | Mouse Cursor Up ↔ Down |
|
||||
|`KC_WH_L` ↔ `KC_WH_R` | Mouse Wheel Left ↔ Right |
|
||||
|`KC_WH_U` ↔ `KC_WH_D` | Mouse Wheel Up ↔ Down |
|
||||
|
||||
**Misc**
|
||||
|
||||
|Keycodes |Description |
|
||||
|-----------------------------------|-----------------------------------|
|
||||
|`KC_BSPC` ↔ `KC_DEL` | Backspace ↔ Delete |
|
||||
|`KC_LBRC` ↔ `KC_RBRC` | `[` ↔ `]` |
|
||||
|`KC_LCBR` ↔ `KC_RCBR` | `{` ↔ `}` |
|
||||
|
||||
**Media**
|
||||
|
||||
|Keycodes |Description |
|
||||
|-----------------------------------|-----------------------------------|
|
||||
|`KC_WBAK` ↔ `KC_WFWD` | Browser Back ↔ Forward |
|
||||
|`KC_MNXT` ↔ `KC_MPRV` | Next ↔ Previous Media Track |
|
||||
|`KC_MFFD` ↔ `KC_MRWD` | Fast Forward ↔ Rewind Media |
|
||||
|`KC_VOLU` ↔ `KC_VOLD` | Volume Up ↔ Down |
|
||||
|`KC_BRIU` ↔ `KC_BRID` | Brightness Up ↔ Down |
|
||||
|
||||
**Hotkeys in Vim, Emacs, and other programs**
|
||||
|
||||
|Keycodes |Description |
|
||||
|-----------------------------------|-----------------------------------|
|
||||
|mod + `KC_F` ↔ mod + `KC_B` | Forward ↔ Backward |
|
||||
|mod + `KC_D` ↔ mod + `KC_U` | Down ↔ Up |
|
||||
|mod + `KC_N` ↔ mod + `KC_P` | Next ↔ Previous |
|
||||
|mod + `KC_A` ↔ mod + `KC_E` | Home ↔ End |
|
||||
|mod + `KC_O` ↔ mod + `KC_I` | Vim jump list Older ↔ Newer |
|
||||
|`KC_J` ↔ `KC_K` | Down ↔ Up |
|
||||
|`KC_H` ↔ `KC_L` | Left ↔ Right |
|
||||
|`KC_W` ↔ `KC_B` | Forward ↔ Backward by Word |
|
||||
|
||||
(where above, "mod" is Ctrl, Alt, or GUI)
|
||||
|
||||
|
||||
## Defining alternate keys
|
||||
|
||||
Use the `get_alt_repeat_key_keycode_user()` callback to define the "alternate"
|
||||
for additional keys or override the default definitions. For example, to define
|
||||
Ctrl + Y as the alternate of Ctrl + Z, and vice versa, add the following in
|
||||
keymap.c:
|
||||
|
||||
```c
|
||||
uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) {
|
||||
if ((mods & MOD_MASK_CTRL)) { // Was Ctrl held?
|
||||
switch (keycode) {
|
||||
case KC_Y: return C(KC_Z); // Ctrl + Y reverses to Ctrl + Z.
|
||||
case KC_Z: return C(KC_Y); // Ctrl + Z reverses to Ctrl + Y.
|
||||
}
|
||||
}
|
||||
|
||||
return KC_TRNS; // Defer to default definitions.
|
||||
}
|
||||
```
|
||||
|
||||
The `keycode` and `mods` args are the keycode and mods that were active with the
|
||||
last pressed key. The meaning of the return value from this function is:
|
||||
|
||||
* `KC_NO` – do nothing (any predefined alternate key is not used);
|
||||
* `KC_TRNS` – use the default alternate key if it exists;
|
||||
* anything else – use the specified keycode. Any keycode may be returned
|
||||
as an alternate key, including custom keycodes.
|
||||
|
||||
Another example, defining Shift + Tab as the alternate of Tab, and vice versa:
|
||||
|
||||
```c
|
||||
uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) {
|
||||
bool shifted = (mods & MOD_MASK_SHIFT); // Was Shift held?
|
||||
switch (keycode) {
|
||||
case KC_TAB:
|
||||
if (shifted) { // If the last key was Shift + Tab,
|
||||
return KC_TAB; // ... the reverse is Tab.
|
||||
} else { // Otherwise, the last key was Tab,
|
||||
return S(KC_TAB); // ... and the reverse is Shift + Tab.
|
||||
}
|
||||
}
|
||||
|
||||
return KC_TRNS;
|
||||
}
|
||||
```
|
||||
|
||||
#### Eliminating SFBs
|
||||
|
||||
Alternate Repeat can be configured more generally to perform an action that
|
||||
"complements" the last key. Alternate Repeat is not limited to reverse
|
||||
repeating, and it need not be symmetric. You can use it to eliminate cases of
|
||||
same-finger bigrams in your layout, that is, pairs of letters typed by the same
|
||||
finger. The following addresses the top 5 same-finger bigrams in English on
|
||||
QWERTY, so that for instance "`ed`" may be typed as <kbd>E</kbd>, <kbd>Alt
|
||||
Repeat</kbd>.
|
||||
|
||||
```c
|
||||
uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) {
|
||||
switch (keycode) {
|
||||
case KC_E: return KC_D; // For "ED" bigram.
|
||||
case KC_D: return KC_E; // For "DE" bigram.
|
||||
case KC_C: return KC_E; // For "CE" bigram.
|
||||
case KC_L: return KC_O; // For "LO" bigram.
|
||||
case KC_U: return KC_N; // For "UN" bigram.
|
||||
}
|
||||
|
||||
return KC_TRNS;
|
||||
}
|
||||
```
|
||||
|
||||
#### Typing shortcuts
|
||||
|
||||
A useful possibility is having Alternate Repeat press [a
|
||||
macro](feature_macros.md). This way macros can be used without having to
|
||||
dedicate keys to them. The following defines a couple shortcuts.
|
||||
|
||||
* Typing <kbd>K</kbd>, <kbd>Alt Repeat</kbd> produces "`keyboard`," with the
|
||||
initial "`k`" typed as usual and the "`eybord`" produced by the macro.
|
||||
* Typing <kbd>.</kbd>, <kbd>Alt Repeat</kbd> produces "`../`," handy for "up
|
||||
directory" on the shell. Similary, <kbd>.</kbd> types the initial "`.`" and
|
||||
"`./`" is produced by the macro.
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
M_KEYBOARD = SAFE_RANGE,
|
||||
M_UPDIR,
|
||||
// Other custom keys...
|
||||
};
|
||||
|
||||
uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) {
|
||||
switch (keycode) {
|
||||
case KC_K: return M_KEYBOARD;
|
||||
case KC_DOT: return M_UPDIR;
|
||||
}
|
||||
|
||||
return KC_TRNS;
|
||||
}
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||
switch (keycode) {
|
||||
case M_KEYBOARD: SEND_STRING(/*k*/"eyboard"); break;
|
||||
case M_UPDIR: SEND_STRING(/*.*/"./"); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## Ignoring certain keys and mods
|
||||
|
||||
In tracking what is "the last key" to be repeated or alternate repeated,
|
||||
modifier and layer switch keys are always ignored. This makes it possible to set
|
||||
some mods and change layers between pressing a key and repeating it. By default,
|
||||
all other (non-modifier, non-layer switch) keys are remembered so that they are
|
||||
eligible for repeating. To configure additional keys to be ignored, define
|
||||
`remember_last_key_user()` in your keymap.c.
|
||||
|
||||
#### Ignoring a key
|
||||
|
||||
The following ignores the Backspace key:
|
||||
|
||||
```c
|
||||
bool remember_last_key_user(uint16_t keycode, keyrecord_t* record,
|
||||
uint8_t* remembered_mods) {
|
||||
switch (keycode) {
|
||||
case KC_BSPC:
|
||||
return false; // Ignore backspace.
|
||||
}
|
||||
|
||||
return true; // Other keys can be repeated.
|
||||
}
|
||||
```
|
||||
|
||||
Then for instance, the Repeat key in <kbd>Left Arrow</kbd>,
|
||||
<kbd>Backspace</kbd>, <kbd>Repeat</kbd> sends Left Arrow again instead of
|
||||
repeating Backspace.
|
||||
|
||||
The `remember_last_key_user()` callback is called on every key press excluding
|
||||
modifiers and layer switches. Returning true indicates the key is remembered,
|
||||
while false means it is ignored.
|
||||
|
||||
#### Filtering remembered mods
|
||||
|
||||
The `remembered_mods` arg represents the mods that will be remembered with
|
||||
this key. It can be modified to forget certain mods. This may be
|
||||
useful to forget capitalization when repeating shifted letters, so that "Aaron"
|
||||
does not becom "AAron":
|
||||
|
||||
```c
|
||||
bool remember_last_key_user(uint16_t keycode, keyrecord_t* record,
|
||||
uint8_t* remembered_mods) {
|
||||
// Forget Shift on letter keys when Shift or AltGr are the only mods.
|
||||
switch (keycode) {
|
||||
case KC_A ... KC_Z:
|
||||
if ((*remembered_mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT))) == 0) {
|
||||
*remembered_mods &= ~MOD_MASK_SHIFT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
#### Further conditions
|
||||
|
||||
Besides checking the keycode, this callback could also make conditions based on
|
||||
the current layer state (with `IS_LAYER_ON(layer)`) or mods (`get_mods()`). For
|
||||
example, the following ignores keys on layer 2 as well as key combinations
|
||||
involving GUI:
|
||||
|
||||
```c
|
||||
bool remember_last_key_user(uint16_t keycode, keyrecord_t* record,
|
||||
uint8_t* remembered_mods) {
|
||||
if (IS_LAYER_ON(2) || (get_mods() & MOD_MASK_GUI)) {
|
||||
return false; // Ignore layer 2 keys and GUI chords.
|
||||
}
|
||||
|
||||
return true; // Other keys can be repeated.
|
||||
}
|
||||
```
|
||||
|
||||
?> See [Layer Functions](feature_layers.md#functions) and [Checking Modifier
|
||||
State](feature_advanced_keycodes.md#checking-modifier-state) for further
|
||||
details.
|
||||
|
||||
|
||||
## Handle how a key is repeated
|
||||
|
||||
By default, pressing the Repeat Key will simply behave as if the last key
|
||||
were pressed again. This also works with macro keys with custom handlers,
|
||||
invoking the macro again. In case fine-tuning is needed for sensible repetition,
|
||||
you can handle how a key is repeated with `get_repeat_key_count()` within
|
||||
`process_record_user()`.
|
||||
|
||||
The `get_repeat_key_count()` function returns a signed count of times the key
|
||||
has been repeated or alternate repeated. When a key is pressed as usual,
|
||||
`get_repeat_key_count()` is 0. On the first repeat, it is 1, then the second
|
||||
repeat, 2, and so on. Negative counts are used similarly for alternate
|
||||
repeating. For instance supposing `MY_MACRO` is a custom keycode used in the
|
||||
layout:
|
||||
|
||||
```c
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||
switch (keycode) {
|
||||
case MY_MACRO:
|
||||
if (get_repeat_key_count() > 0) {
|
||||
// MY_MACRO is being repeated!
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("repeat!");
|
||||
}
|
||||
} else {
|
||||
// MY_MACRO is being used normally.
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("macro");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
// Other macros...
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## Handle how a key is alternate repeated
|
||||
|
||||
Pressing the Alternate Repeat Key behaves as if the "alternate" of the last
|
||||
pressed key were pressed, if an alternate is defined. To define how a particular
|
||||
key is alternate repeated, use the `get_alt_repeat_key_keycode_user()` callback
|
||||
as described above to define which keycode to use as its alternate. Beyond this,
|
||||
`get_repeat_key_count()` may be used in custom handlers to fine-tune behavior
|
||||
when alternate repeating.
|
||||
|
||||
The following example defines `MY_MACRO` as its own alternate, and specially
|
||||
handles repeating and alternate repeating:
|
||||
|
||||
```c
|
||||
uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) {
|
||||
switch (keycode) {
|
||||
case MY_MACRO: return MY_MACRO; // MY_MACRO is its own alternate.
|
||||
}
|
||||
return KC_TRNS;
|
||||
}
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||
switch (keycode) {
|
||||
case MY_MACRO:
|
||||
if (get_repeat_key_count() > 0) { // Repeating.
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("repeat!");
|
||||
}
|
||||
} else if (get_repeat_key_count() < 0) { // Alternate repeating.
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("alt repeat!");
|
||||
}
|
||||
} else { // Used normally.
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("macro");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
// Other macros...
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Functions
|
||||
|
||||
| Function | Description |
|
||||
|--------------------------------|------------------------------------------------------------------------|
|
||||
| `get_last_keycode()` | The last key's keycode, the key to be repeated. |
|
||||
| `get_last_mods()` | Mods to apply when repeating. |
|
||||
| `set_last_keycode(kc)` | Set the keycode to be repeated. |
|
||||
| `set_last_mods(mods)` | Set the mods to apply when repeating. |
|
||||
| `get_repeat_key_count()` | Signed count of times the key has been repeated or alternate repeated. |
|
||||
| `get_alt_repeat_key_keycode()` | Keycode to be used for alternate repeating. |
|
||||
|
||||
|
||||
## Additional "Alternate" keys
|
||||
|
||||
By leveraging `get_last_keycode()` in macros, it is possible to define
|
||||
additional, distinct "Alternate Repeat"-like keys. The following defines two
|
||||
keys `ALTREP2` and `ALTREP3` and implements ten shortcuts with them for common
|
||||
English 5-gram letter patterns, taking inspiration from
|
||||
[Stenotype](feature_stenography.md):
|
||||
|
||||
|
||||
| Typing | Produces | Typing | Produces |
|
||||
|----------------------------------|----------|----------------------------------|----------|
|
||||
| <kbd>A</kbd>, <kbd>ALTREP2</kbd> | `ation` | <kbd>A</kbd>, <kbd>ALTREP3</kbd> | `about` |
|
||||
| <kbd>I</kbd>, <kbd>ALTREP2</kbd> | `ition` | <kbd>I</kbd>, <kbd>ALTREP3</kbd> | `inter` |
|
||||
| <kbd>S</kbd>, <kbd>ALTREP2</kbd> | `ssion` | <kbd>S</kbd>, <kbd>ALTREP3</kbd> | `state` |
|
||||
| <kbd>T</kbd>, <kbd>ALTREP2</kbd> | `their` | <kbd>T</kbd>, <kbd>ALTREP3</kbd> | `there` |
|
||||
| <kbd>W</kbd>, <kbd>ALTREP2</kbd> | `which` | <kbd>W</kbd>, <kbd>ALTREP3</kbd> | `would` |
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
ALTREP2 = SAFE_RANGE,
|
||||
ALTREP3,
|
||||
};
|
||||
|
||||
// Use ALTREP2 and ALTREP3 in your layout...
|
||||
|
||||
bool remember_last_key_user(uint16_t keycode, keyrecord_t* record,
|
||||
uint8_t* remembered_mods) {
|
||||
switch (keycode) {
|
||||
case ALTREP2:
|
||||
case ALTREP3:
|
||||
return false; // Ignore ALTREP keys.
|
||||
}
|
||||
|
||||
return true; // Other keys can be repeated.
|
||||
}
|
||||
|
||||
static void process_altrep2(uint16_t keycode, uint8_t mods) {
|
||||
switch (keycode) {
|
||||
case KC_A: SEND_STRING(/*a*/"tion"); break;
|
||||
case KC_I: SEND_STRING(/*i*/"tion"); break;
|
||||
case KC_S: SEND_STRING(/*s*/"sion"); break;
|
||||
case KC_T: SEND_STRING(/*t*/"heir"); break;
|
||||
case KC_W: SEND_STRING(/*w*/"hich"); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_altrep3(uint16_t keycode, uint8_t mods) {
|
||||
switch (keycode) {
|
||||
case KC_A: SEND_STRING(/*a*/"bout"); break;
|
||||
case KC_I: SEND_STRING(/*i*/"nter"); break;
|
||||
case KC_S: SEND_STRING(/*s*/"tate"); break;
|
||||
case KC_T: SEND_STRING(/*t*/"here"); break;
|
||||
case KC_W: SEND_STRING(/*w*/"ould"); break;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||
switch (keycode) {
|
||||
case ALTREP2:
|
||||
if (record->event.pressed) {
|
||||
process_altrep2(get_last_keycode(), get_last_mods());
|
||||
}
|
||||
return false;
|
||||
|
||||
case ALTREP3:
|
||||
if (record->event.pressed) {
|
||||
process_altrep3(get_last_keycode(), get_last_mods());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
@ -12,7 +12,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = IS31FL3731
|
||||
RGB_MATRIX_DRIVER = is31fl3731
|
||||
```
|
||||
|
||||
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
|
||||
@ -76,7 +76,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = IS31FL3733
|
||||
RGB_MATRIX_DRIVER = is31fl3733
|
||||
```
|
||||
|
||||
You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
|
||||
@ -156,13 +156,89 @@ const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
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).
|
||||
|
||||
---
|
||||
### IS31FL3736 :id=is31fl3736
|
||||
|
||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3736 RGB controller. To enable it, add this to your `rules.mk`:
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
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.
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
|
||||
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
||||
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
|
||||
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
|
||||
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
|
||||
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
|
||||
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
|
||||
| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
|
||||
|
||||
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:
|
||||
|
||||
| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
|
||||
|----------------------|-------------|
|
||||
| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
|
||||
| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
|
||||
| `PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
|
||||
| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
|
||||
| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
|
||||
| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
|
||||
| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
|
||||
| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
|
||||
|
||||
Here is an example using 2 drivers.
|
||||
|
||||
```c
|
||||
// This is a 7-bit address, that gets left-shifted and bit 0
|
||||
// set to 0 for write, 1 for read (as per I2C protocol)
|
||||
// The address will vary depending on your wiring:
|
||||
// 0000 <-> GND
|
||||
// 0101 <-> SCL
|
||||
// 1010 <-> SDA
|
||||
// 1111 <-> VCC
|
||||
// ADDR represents A3:A0 of the 7-bit address.
|
||||
// The result is: 0b101(ADDR)
|
||||
#define DRIVER_ADDR_1 0b1010000
|
||||
#define DRIVER_ADDR_2 0b1010001
|
||||
|
||||
#define DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 30
|
||||
#define DRIVER_2_LED_TOTAL 32
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
```
|
||||
!> 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`.
|
||||
|
||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
* | | G location
|
||||
* | | | B location
|
||||
* | | | | */
|
||||
{0, B_1, A_1, C_1},
|
||||
....
|
||||
}
|
||||
```
|
||||
### IS31FL3737 :id=is31fl3737
|
||||
|
||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3737 RGB controller. To enable it, add this to your `rules.mk`:
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = IS31FL3737
|
||||
RGB_MATRIX_DRIVER = is31fl3737
|
||||
```
|
||||
You can use between 1 and 4 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard.
|
||||
|
||||
@ -218,8 +294,6 @@ 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`.
|
||||
|
||||
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
|
||||
|
||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
@ -312,7 +386,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
|
||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
const is31_led __flash g_is31_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
@ -332,7 +406,7 @@ Eg `#define ISSI_MANUAL_SCALING 3`
|
||||
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
|
||||
const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
|
||||
* LED Index
|
||||
* | R scaling
|
||||
* | | G scaling
|
||||
@ -354,14 +428,14 @@ There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = WS2812
|
||||
RGB_MATRIX_DRIVER = ws2812
|
||||
```
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
|
||||
```c
|
||||
// The pin connected to the data pin of the LEDs
|
||||
#define RGB_DI_PIN D7
|
||||
#define WS2812_DI_PIN D7
|
||||
// The number of LEDs connected
|
||||
#define RGB_MATRIX_LED_COUNT 70
|
||||
```
|
||||
@ -376,16 +450,16 @@ There is basic support for APA102 based addressable LED strands. To enable it, a
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = APA102
|
||||
RGB_MATRIX_DRIVER = apa102
|
||||
```
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
|
||||
```c
|
||||
// The pin connected to the data pin of the LEDs
|
||||
#define RGB_DI_PIN D7
|
||||
#define APA102_DI_PIN D7
|
||||
// The pin connected to the clock pin of the LEDs
|
||||
#define RGB_CI_PIN D6
|
||||
#define APA102_CI_PIN D6
|
||||
// The number of LEDs connected
|
||||
#define RGB_MATRIX_LED_COUNT 70
|
||||
```
|
||||
@ -396,7 +470,7 @@ There is basic support for addressable RGB matrix lighting with the SPI AW20216
|
||||
|
||||
```make
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = AW20216
|
||||
RGB_MATRIX_DRIVER = aw20216
|
||||
```
|
||||
|
||||
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`:
|
||||
@ -576,11 +650,8 @@ enum rgb_matrix_effects {
|
||||
RGB_MATRIX_PIXEL_FRACTAL, // Single hue fractal filled keys pulsing horizontally out to edges
|
||||
RGB_MATRIX_PIXEL_FLOW, // Pulsing RGB flow along LED wiring with random hues
|
||||
RGB_MATRIX_PIXEL_RAIN, // Randomly light keys with random hues
|
||||
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
|
||||
RGB_MATRIX_TYPING_HEATMAP, // How hot is your WPM!
|
||||
RGB_MATRIX_DIGITAL_RAIN, // That famous computer simulation
|
||||
#endif
|
||||
#if defined(RGB_MATRIX_KEYPRESSES) || defined(RGB_MATRIX_KEYRELEASES)
|
||||
RGB_MATRIX_SOLID_REACTIVE_SIMPLE, // Pulses keys hit to hue & value then fades value out
|
||||
RGB_MATRIX_SOLID_REACTIVE, // Static single hue, pulses keys hit to shifted hue then fades to current hue
|
||||
RGB_MATRIX_SOLID_REACTIVE_WIDE // Hue & value pulse near a single key hit then fades value out
|
||||
@ -593,7 +664,6 @@ enum rgb_matrix_effects {
|
||||
RGB_MATRIX_MULTISPLASH, // Full gradient & value pulse away from multiple key hits then fades value out
|
||||
RGB_MATRIX_SOLID_SPLASH, // Hue & value pulse away from a single key hit then fades value out
|
||||
RGB_MATRIX_SOLID_MULTISPLASH, // Hue & value pulse away from multiple key hits then fades value out
|
||||
#endif
|
||||
RGB_MATRIX_EFFECT_MAX
|
||||
};
|
||||
```
|
||||
@ -633,14 +703,12 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|
||||
|`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` |
|
||||
|`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` |
|
||||
|
||||
?> These modes don't require any additional defines.
|
||||
|
||||
|Framebuffer Defines |Description |
|
||||
|------------------------------------------------------|----------------------------------------------|
|
||||
|`#define ENABLE_RGB_MATRIX_TYPING_HEATMAP` |Enables `RGB_MATRIX_TYPING_HEATMAP` |
|
||||
|`#define ENABLE_RGB_MATRIX_DIGITAL_RAIN` |Enables `RGB_MATRIX_DIGITAL_RAIN` |
|
||||
|
||||
?> These modes also require the `RGB_MATRIX_FRAMEBUFFER_EFFECTS` define to be available.
|
||||
?> These modes introduce additional logic that can increase firmware size.
|
||||
|
||||
|Reactive Defines |Description |
|
||||
|------------------------------------------------------|----------------------------------------------|
|
||||
@ -657,7 +725,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|
||||
|`#define ENABLE_RGB_MATRIX_SOLID_SPLASH` |Enables `RGB_MATRIX_SOLID_SPLASH` |
|
||||
|`#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Enables `RGB_MATRIX_SOLID_MULTISPLASH` |
|
||||
|
||||
?> These modes also require the `RGB_MATRIX_KEYPRESSES` or `RGB_MATRIX_KEYRELEASES` define to be available.
|
||||
?> These modes introduce additional logic that can increase firmware size.
|
||||
|
||||
|
||||
### RGB Matrix Effect Typing Heatmap :id=rgb-matrix-effect-typing-heatmap
|
||||
@ -690,6 +758,14 @@ Remove the spread effect entirely.
|
||||
#define RGB_MATRIX_TYPING_HEATMAP_SLIM
|
||||
```
|
||||
|
||||
It's also possible to adjust the tempo of *heating up*. It's defined as the number of shades that are
|
||||
increased on the [HSV scale](https://en.wikipedia.org/wiki/HSL_and_HSV). Decreasing this value increases
|
||||
the number of keystrokes needed to fully heat up the key.
|
||||
|
||||
```c
|
||||
#define RGB_MATRIX_TYPING_HEATMAP_INCREASE_STEP 32
|
||||
```
|
||||
|
||||
### RGB Matrix Effect Solid Reactive :id=rgb-matrix-effect-solid-reactive
|
||||
|
||||
Solid reactive effects will pulse RGB light on key presses with user configurable hues. To enable gradient mode that will automatically change reactive color, add the following define:
|
||||
@ -790,9 +866,7 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
|
||||
## Additional `config.h` Options :id=additional-configh-options
|
||||
|
||||
```c
|
||||
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
|
||||
#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
|
||||
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
|
||||
#define RGB_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
|
||||
#define RGB_MATRIX_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
|
||||
#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
|
||||
#define RGB_MATRIX_LED_PROCESS_LIMIT (RGB_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
|
||||
@ -805,19 +879,13 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
|
||||
#define RGB_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
|
||||
#define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature)
|
||||
#define RGB_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
|
||||
// If RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
|
||||
// If reactive effects are enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
|
||||
#define RGB_TRIGGER_ON_KEYDOWN // Triggers RGB keypress events on key down. This makes RGB control feel more responsive. This may cause RGB to not function properly on some boards
|
||||
```
|
||||
|
||||
## EEPROM storage :id=eeprom-storage
|
||||
|
||||
The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
|
||||
|
||||
```c
|
||||
#define EECONFIG_RGB_MATRIX (uint32_t *)28
|
||||
```
|
||||
|
||||
Where `28` is an unused index from `eeconfig.h`.
|
||||
The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time).
|
||||
|
||||
## Functions :id=functions
|
||||
|
||||
@ -888,7 +956,7 @@ Where `28` is an unused index from `eeconfig.h`.
|
||||
|
||||
### 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
|
||||
bool rgb_matrix_indicators_kb(void) {
|
||||
if (!rgb_matrix_indicators_user()) {
|
||||
|
@ -28,17 +28,18 @@ For APA102 LEDs, add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
RGBLIGHT_ENABLE = yes
|
||||
RGBLIGHT_DRIVER = APA102
|
||||
RGBLIGHT_DRIVER = apa102
|
||||
```
|
||||
|
||||
At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. For APA102 LEDs, you must also define the clock pin. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these.
|
||||
|
||||
|Define |Description |
|
||||
|---------------|---------------------------------------------------------------------------------------------------------|
|
||||
|`RGB_DI_PIN` |The pin connected to the data pin of the LEDs |
|
||||
|`RGB_CI_PIN` |The pin connected to the clock pin of the LEDs (APA102 only) |
|
||||
|`RGBLED_NUM` |The number of LEDs connected |
|
||||
|`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half directly wired to `RGB_DI_PIN` |
|
||||
|Define |Description |
|
||||
|---------------|-------------------------------------------------------------------------|
|
||||
|`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_CI_PIN`|The pin connected to the clock pin of the LEDs (APA102) |
|
||||
|`RGBLED_NUM` |The number of LEDs connected |
|
||||
|`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.
|
||||
|
||||
@ -89,7 +90,7 @@ Your RGB lighting can be configured by placing these `#define`s in your `config.
|
||||
|
||||
|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_VAL_STEP` |`17` |The number of steps to increment the brightness by |
|
||||
|`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level |
|
||||
@ -523,37 +524,6 @@ By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED
|
||||
```
|
||||
<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
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Send String
|
||||
# Send String :id=send-string
|
||||
|
||||
The Send String API is part of QMK's macro system. It allows for sequences of keystrokes to be sent automatically.
|
||||
|
||||
@ -6,7 +6,7 @@ The full ASCII character set is supported, along with all of the keycodes in the
|
||||
|
||||
?> Unicode characters are **not** supported with this API -- see the [Unicode](feature_unicode.md) feature instead.
|
||||
|
||||
## Usage
|
||||
## Usage :id=usage
|
||||
|
||||
Send String is enabled by default, so there is usually no need for any special setup. However, if it is disabled, add the following to your `rules.mk`:
|
||||
|
||||
@ -14,7 +14,7 @@ Send String is enabled by default, so there is usually no need for any special s
|
||||
SEND_STRING_ENABLE = yes
|
||||
```
|
||||
|
||||
## Basic Configuration
|
||||
## Basic Configuration :id=basic-configuration
|
||||
|
||||
Add the following to your `config.h`:
|
||||
|
||||
@ -23,7 +23,7 @@ Add the following to your `config.h`:
|
||||
|`SENDSTRING_BELL`|*Not defined* |If the [Audio](feature_audio.md) feature is enabled, the `\a` character (ASCII `BEL`) will beep the speaker.|
|
||||
|`BELL_SOUND` |`TERMINAL_SOUND`|The song to play when the `\a` character is encountered. By default, this is an eighth note of C5. |
|
||||
|
||||
## Keycodes
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
The Send String functions accept C string literals, but specific keycodes can be injected with the below macros. All of the keycodes in the [Basic Keycode range](keycodes_basic.md) are supported (as these are the only ones that will actually be sent to the host), but with an `X_` prefix instead of `KC_`.
|
||||
|
||||
@ -44,13 +44,13 @@ The following characters are also mapped to their respective keycodes for conven
|
||||
|`\t` |`\x1B`|`TAB`|`KC_TAB` |
|
||||
| |`\x7F`|`DEL`|`KC_DELETE` |
|
||||
|
||||
### Language Support
|
||||
### Language Support :id=language-support
|
||||
|
||||
By default, Send String assumes your OS keyboard layout is set to US ANSI. If you are using a different keyboard layout, you can [override the lookup tables used to convert ASCII characters to keystrokes](reference_keymap_extras.md#sendstring-support).
|
||||
|
||||
## Examples
|
||||
## Examples :id=examples
|
||||
|
||||
### Hello World
|
||||
### Hello World :id=example-hello-world
|
||||
|
||||
A simple custom keycode which types out "Hello, world!" and the Enter key when pressed.
|
||||
|
||||
@ -70,7 +70,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
```
|
||||
|
||||
### Keycode Injection
|
||||
### Keycode Injection :id=example-keycode-injection
|
||||
|
||||
This example types out opening and closing curly braces, then taps the left arrow key to move the cursor between the two.
|
||||
|
||||
@ -84,26 +84,26 @@ This example types Ctrl+A, then Ctrl+C, without releasing Ctrl.
|
||||
SEND_STRING(SS_LCTL("ac"));
|
||||
```
|
||||
|
||||
## API
|
||||
## API :id=api
|
||||
|
||||
### `void send_string(const char *string)`
|
||||
### `void send_string(const char *string)` :id=api-send-string
|
||||
|
||||
Type out a string of ASCII characters.
|
||||
|
||||
This function simply calls `send_string_with_delay(string, 0)`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-string-arguments
|
||||
|
||||
- `const char *string`
|
||||
The string to type out.
|
||||
|
||||
---
|
||||
|
||||
### `void send_string_with_delay(const char *string, uint8_t interval)`
|
||||
### `void send_string_with_delay(const char *string, uint8_t interval)` :id=api-send-string-with-delay
|
||||
|
||||
Type out a string of ASCII characters, with a delay between each character.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-string-with-delay-arguments
|
||||
|
||||
- `const char *string`
|
||||
The string to type out.
|
||||
@ -112,26 +112,26 @@ Type out a string of ASCII characters, with a delay between each character.
|
||||
|
||||
---
|
||||
|
||||
### `void send_string_P(const char *string)`
|
||||
### `void send_string_P(const char *string)` :id=api-send-string-p
|
||||
|
||||
Type out a PROGMEM string of ASCII characters.
|
||||
|
||||
On ARM devices, this function is simply an alias for `send_string_with_delay(string, 0)`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-string-p-arguments
|
||||
|
||||
- `const char *string`
|
||||
The string to type out.
|
||||
|
||||
---
|
||||
|
||||
### `void send_string_with_delay_P(const char *string, uint8_t interval)`
|
||||
### `void send_string_with_delay_P(const char *string, uint8_t interval)` :id=api-send-string-with-delay-p
|
||||
|
||||
Type out a PROGMEM string of ASCII characters, with a delay between each character.
|
||||
|
||||
On ARM devices, this function is simply an alias for `send_string_with_delay(string, interval)`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-string-with-delay-p-arguments
|
||||
|
||||
- `const char *string`
|
||||
The string to type out.
|
||||
@ -140,76 +140,76 @@ On ARM devices, this function is simply an alias for `send_string_with_delay(str
|
||||
|
||||
---
|
||||
|
||||
### `void send_char(char ascii_code)`
|
||||
### `void send_char(char ascii_code)` :id=api-send-char
|
||||
|
||||
Type out an ASCII character.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-char-arguments
|
||||
|
||||
- `char ascii_code`
|
||||
The character to type.
|
||||
|
||||
---
|
||||
|
||||
### `void send_dword(uint32_t number)`
|
||||
### `void send_dword(uint32_t number)` :id=api-send-dword
|
||||
|
||||
Type out an eight digit (unsigned 32-bit) hexadecimal value.
|
||||
|
||||
The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-dword-arguments
|
||||
|
||||
- `uint32_t number`
|
||||
The value to type, from 0 to 4,294,967,295.
|
||||
|
||||
---
|
||||
|
||||
### `void send_word(uint16_t number)`
|
||||
### `void send_word(uint16_t number)` :id=api-send-word
|
||||
|
||||
Type out a four digit (unsigned 16-bit) hexadecimal value.
|
||||
|
||||
The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-word-arguments
|
||||
|
||||
- `uint16_t number`
|
||||
The value to type, from 0 to 65,535.
|
||||
|
||||
---
|
||||
|
||||
### `void send_byte(uint8_t number)`
|
||||
### `void send_byte(uint8_t number)` :id=api-send-bytes
|
||||
|
||||
Type out a two digit (8-bit) hexadecimal value.
|
||||
|
||||
The format is `[0-9a-f]{2}`, eg. `00` through `ff`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-byte-arguments
|
||||
|
||||
- `uint8_t number`
|
||||
The value to type, from 0 to 255.
|
||||
|
||||
---
|
||||
|
||||
### `void send_nibble(uint8_t number)`
|
||||
### `void send_nibble(uint8_t number)` :id=api-send-nibble
|
||||
|
||||
Type out a single hexadecimal digit.
|
||||
|
||||
The format is `[0-9a-f]{1}`, eg. `0` through `f`.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-send-nibble-arguments
|
||||
|
||||
- `uint8_t number`
|
||||
The value to type, from 0 to 15.
|
||||
|
||||
---
|
||||
|
||||
### `void tap_random_base64(void)`
|
||||
### `void tap_random_base64(void)` :id=api-tap-random-base64
|
||||
|
||||
Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`.
|
||||
|
||||
---
|
||||
|
||||
### `SEND_STRING(string)`
|
||||
### `SEND_STRING(string)` :id=api-send-string-macro
|
||||
|
||||
Shortcut macro for `send_string_with_delay_P(PSTR(string), 0)`.
|
||||
|
||||
@ -217,7 +217,7 @@ On ARM devices, this define evaluates to `send_string_with_delay(string, 0)`.
|
||||
|
||||
---
|
||||
|
||||
### `SEND_STRING_DELAY(string, interval)`
|
||||
### `SEND_STRING_DELAY(string, interval)` :id=api-send-string-delay-macro
|
||||
|
||||
Shortcut macro for `send_string_with_delay_P(PSTR(string), interval)`.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Space Cadet: The Future, Built In
|
||||
|
||||
Steve Losh described the [Space Cadet Shift](https://stevelosh.com/blog/2012/10/a-modern-space-cadet/) quite well. Essentially, when you tap Left Shift on its own, you get an opening parenthesis; tap Right Shift on its own and you get the closing one. When held, the Shift keys function as normal. Yes, it's as cool as it sounds, and now even cooler supporting Control and Alt as well!
|
||||
Steve Losh described the [Space Cadet Shift](https://web.archive.org/web/20230330090938/https://stevelosh.com/blog/2012/10/a-modern-space-cadet/) quite well. Essentially, when you tap Left Shift on its own, you get an opening parenthesis; tap Right Shift on its own and you get the closing one. When held, the Shift keys function as normal. Yes, it's as cool as it sounds, and now even cooler supporting Control and Alt as well!
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -300,6 +300,12 @@ This enables transmitting the pointing device status to the master side of the s
|
||||
|
||||
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.
|
||||
|
||||
```c
|
||||
#define SPLIT_ACTIVITY_ENABLE
|
||||
```
|
||||
|
||||
This synchronizes the activity timestamps between sides of the split keyboard, allowing for activity timeouts to occur.
|
||||
|
||||
### Custom data sync between sides :id=custom-data-sync
|
||||
|
||||
QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
|
||||
|
@ -138,7 +138,7 @@ bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t
|
||||
|
||||
This function is called after a key has been processed, but before any decision about whether or not to send a chord. This is where to put hooks for things like, say, live displays of steno chords or keys.
|
||||
|
||||
If `IS_PRESSED(record->event)` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
|
||||
If `record->event.pressed` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
|
||||
|
||||
The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[STN_E, STN_U, STN_BR, STN_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice.
|
||||
|
||||
|
@ -47,6 +47,11 @@ const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS] = { 1, 0 };
|
||||
|
||||
### Functions :id=functions
|
||||
|
||||
| Function | Description |
|
||||
|----------------------|---------------------------------------------|
|
||||
| `is_swap_hands_on()` | Returns true if Swap-Hands is currently on. |
|
||||
User callback functions to manipulate Swap-Hands:
|
||||
|
||||
| Function | Description |
|
||||
|-----------------------|---------------------------------------------|
|
||||
| `swap_hands_on()` | Turns Swap-Hands on. |
|
||||
| `swap_hands_off()` | Turns Swap-Hands off. |
|
||||
| `swap_hands_toggle()` | Toggles Swap-Hands. |
|
||||
| `is_swap_hands_on()` | Returns true if Swap-Hands is currently on. |
|
||||
|
@ -28,7 +28,7 @@ After this, you'll want to use the `tap_dance_actions` array to specify what act
|
||||
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode).
|
||||
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
|
||||
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(on_each_tap_fn, on_each_release_fn, on_dance_finished_fn, on_dance_reset_fn)`: This macro is identical to `ACTION_TAP_DANCE_FN_ADVANCED` with the addition of `on_each_release_fn` which is invoked every time the key for the tap dance is released. It is worth noting that `on_each_release_fn` will still be called even when the key is released after the dance finishes (e.g. if the key is released after being pressed and held for longer than the `TAPPING_TERM`).
|
||||
|
||||
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
|
||||
|
||||
|
@ -1,48 +1,77 @@
|
||||
# Unicode Support
|
||||
# Unicode :id=unicode
|
||||
|
||||
Unicode characters can be input straight from your keyboard! There are some limitations, however.
|
||||
With a little help from your OS, practically any Unicode character can be input using your keyboard.
|
||||
|
||||
In order to enable Unicode support on your keyboard, you will need to do the following:
|
||||
## Caveats :id=caveats
|
||||
|
||||
1. Choose one of three supported Unicode implementations: [Basic Unicode](#basic-unicode), [Unicode Map](#unicode-map), [UCIS](#ucis).
|
||||
2. Find which [input mode](#input-modes) is the best match for your operating system and setup.
|
||||
3. [Set](#setting-the-input-mode) the appropriate input mode (or modes) in your configuration.
|
||||
4. Add Unicode keycodes to your keymap.
|
||||
There are some limitations to this feature. Because there is no "standard" method of Unicode input across all operating systems, each of them require their own setup process on both the host *and* in the firmware, which may involve installation of additional software. This also means Unicode input will not "just work" when the keyboard is plugged into another device.
|
||||
|
||||
## Usage :id=usage
|
||||
|
||||
## 1. Methods :id=methods
|
||||
The core Unicode API can be used purely programmatically. However, there are also additional subsystems which build on top of it and come with keycodes to make things easier. See below for more details.
|
||||
|
||||
QMK supports three different methods for enabling Unicode input and adding Unicode characters to your keymap. Each has its pros and cons in terms of flexibility and ease of use. Choose the one that best fits your use case.
|
||||
Add the following to your keymap's `rules.mk`:
|
||||
|
||||
The Basic method should be enough for most users. However, if you need a wider range of supported characters (including emoji, rare symbols etc.), you should use Unicode Map.
|
||||
```make
|
||||
UNICODE_COMMON = yes
|
||||
```
|
||||
|
||||
<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
|
||||
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.
|
||||
|
||||
Add the following to your `rules.mk`:
|
||||
To enable Unicode Map, add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
UNICODEMAP_ENABLE = yes
|
||||
```
|
||||
|
||||
Then add `X(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name.
|
||||
Then, you will need to create a mapping table in your `keymap.c`, and (optionally) an enum for naming the array indices, like so:
|
||||
|
||||
```c
|
||||
enum unicode_names {
|
||||
@ -51,242 +80,373 @@ enum unicode_names {
|
||||
SNEK
|
||||
};
|
||||
|
||||
const uint32_t unicode_map[] PROGMEM = {
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
[BANG] = 0x203D, // ‽
|
||||
[IRONY] = 0x2E2E, // ⸮
|
||||
[SNEK] = 0x1F40D, // 🐍
|
||||
};
|
||||
```
|
||||
|
||||
Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
|
||||
Finally, add `UM(i)` keycodes to your keymap, where *i* is an index into the `unicode_map[]` array. If you defined the enum above, you can use those names instead, for example `UM(BANG)` or `UM(SNEK)`.
|
||||
|
||||
#### Lower and Upper Case
|
||||
#### Lower and Upper Case Pairs :id=unicodemap-pairs
|
||||
|
||||
Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
|
||||
Some writing systems have lowercase and uppercase variants of each character, such as å and Å. To make inputting these characters easier, you can use the `UP(i, j)` keycode in your keymap, where *i* and *j* are the mapping table indices of the lowercase and uppercase characters, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the uppercase character will be inserted; otherwise, the lowercase character will be inserted.
|
||||
|
||||
This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP()`. This helps blend Unicode keys in with regular alphas.
|
||||
```c
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
[AE_LOWER] = 0x00E6, // æ
|
||||
[AE_UPPER] = 0x00C6, // Æ
|
||||
};
|
||||
```
|
||||
|
||||
Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L36) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
|
||||
This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key. This helps blend Unicode keys in with regular keycodes.
|
||||
|
||||
<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
|
||||
UCIS_ENABLE = yes
|
||||
```
|
||||
|
||||
Then define a table like this in your keymap file:
|
||||
Then, create a mapping table in your `keymap.c`:
|
||||
|
||||
```c
|
||||
const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
|
||||
UCIS_SYM("poop", 0x1F4A9), // 💩
|
||||
UCIS_SYM("rofl", 0x1F923), // 🤣
|
||||
UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺
|
||||
UCIS_SYM("ukr", 0x1F1FA, 0x1F1E6), // 🇺🇦
|
||||
UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0) // ಠ_ಠ
|
||||
);
|
||||
```
|
||||
|
||||
By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file.
|
||||
By default, each table entry may be up to three code points long. This can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your keymap's `config.h`.
|
||||
|
||||
To use UCIS input, call `ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
|
||||
To invoke UCIS input, the `ucis_start()` function must first be called (for example, in a custom "Unicode" keycode). Then, type the mnemonic for the mapping table entry (such as "rofl"), and hit Space or Enter. The "rofl" text will be backspaced and the emoji inserted.
|
||||
|
||||
#### Customization
|
||||
<!-- 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.
|
||||
* `void ucis_success(uint8_t symbol_index)` – This runs when the input has matched something and has completed. By default, it doesn't do anything.
|
||||
* `void ucis_symbol_fallback (void)` – This runs when the input doesn't match anything. By default, it falls back to trying that input as a Unicode code.
|
||||
Unicode input works by typing a sequence of characters, similar to a macro. However, since this sequence depends on your OS, you will need to prepare both your host machine and QMK to recognise and send the correct Unicode input sequences respectively.
|
||||
|
||||
You can find the default implementations of these functions in [`process_ucis.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c).
|
||||
|
||||
|
||||
## 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`:
|
||||
To set the list of enabled input modes, add the `UNICODE_SELECTED_MODES` define to your keymap's `config.h`, for example:
|
||||
|
||||
```c
|
||||
#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
|
||||
// or
|
||||
#define UNICODE_SELECTED_MODES UNICODE_MODE_MAC, 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
|
||||
#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_LINUX, UNICODE_MODE_WINCOMPOSE
|
||||
<!-- tabs:start -->
|
||||
|
||||
### ** macOS **
|
||||
|
||||
**Mode Name:** `UNICODE_MODE_MAC`
|
||||
|
||||
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 |
|
||||
|----------------------------|---------|-------------------------|-----------------------------------------------------------------------------|
|
||||
|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Next in list |Cycle through selected modes, reverse direction when Shift is held |
|
||||
|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Prev in list |Cycle through selected modes in reverse, forward direction when Shift is held|
|
||||
|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |`UNICODE_MODE_MACOS` |Switch to macOS input |
|
||||
|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|`UNICODE_MODE_LINUX` |Switch to Linux input |
|
||||
|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |`UNICODE_MODE_WINDOWS` |Switch to Windows input |
|
||||
|`QK_UNICODE_MODE_BSD` |`UC_BSD` |`UNICODE_MODE_BSD` |Switch to BSD input _(not implemented)_ |
|
||||
|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|`UNICODE_MODE_WINCOMPOSE`|Switch to Windows input using WinCompose |
|
||||
|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|`UNICODE_MODE_EMACS` |Switch to emacs (`C-x-8 RET`) |
|
||||
### ** BSD **
|
||||
|
||||
You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UNICODE_MODE_LINUX`).
|
||||
**Mode Name:** `UNICODE_MODE_BSD`
|
||||
|
||||
?> Using `UNICODE_SELECTED_MODES` is preferable to calling `set_unicode_input_mode()` in `matrix_init_user()` or similar functions, since it's better integrated into the Unicode system and has the added benefit of avoiding unnecessary writes to EEPROM.
|
||||
Not currently implemented. If you're a BSD user and want to contribute support for this input mode, please [feel free](contributing.md)!
|
||||
|
||||
#### Audio Feedback
|
||||
<!-- 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
|
||||
#define UNICODE_SONG_MAC AUDIO_ON_SOUND
|
||||
#define UNICODE_SONG_LNX UNICODE_LINUX
|
||||
#define UNICODE_SONG_BSD TERMINAL_SOUND
|
||||
#define UNICODE_SONG_WIN UNICODE_WINDOWS
|
||||
#define UNICODE_SONG_WINC UNICODE_WINDOWS
|
||||
```
|
||||
## API :id=api
|
||||
|
||||
### `uint8_t get_unicode_input_mode(void)` :id=api-get-unicode-input-mode
|
||||
|
||||
## Additional Customization
|
||||
Get the current Unicode input mode.
|
||||
|
||||
Because Unicode is a large and versatile feature, there are a number of options you can customize to make it work better on your system.
|
||||
#### Return Value :id=api-get-unicode-input-mode-return-value
|
||||
|
||||
### Start and Finish Input Functions
|
||||
The currently active Unicode input mode.
|
||||
|
||||
The functions for starting and finishing Unicode input on your platform can be overridden locally. Possible uses include customizing input mode behavior if you don't use the default keys, or adding extra visual/audio feedback to Unicode input.
|
||||
---
|
||||
|
||||
* `void unicode_input_start(void)` – This sends the initial sequence that tells your platform to enter Unicode input mode. For example, it holds the left Alt key followed by Num+ on Windows, and presses the `UNICODE_KEY_LNX` combination (default: Ctrl+Shift+U) on Linux.
|
||||
* `void unicode_input_finish(void)` – This is called to exit Unicode input mode, for example by pressing Space or releasing the Alt key.
|
||||
### `void set_unicode_input_mode(uint8_t mode)` :id=api-set-unicode-input-mode
|
||||
|
||||
You can find the default implementations of these functions in [`process_unicode_common.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode_common.c).
|
||||
Set the Unicode input mode.
|
||||
|
||||
### Input Mode Callbacks
|
||||
#### Arguments :id=api-set-unicode-input-mode-arguments
|
||||
|
||||
There are callbacks functions available that are called whenever the unicode input mode changes. The new input mode is passed to the function.
|
||||
- `uint8_t mode`
|
||||
The input mode to set.
|
||||
|
||||
|Callback |Description |
|
||||
|---------------------------------------------------|-----------------------------------------------------|
|
||||
| `unicode_input_mode_set_kb(uint8_t input_mode)` | Callback for unicode input mode set, for keyboard. |
|
||||
| `unicode_input_mode_set_user(uint8_t input_mode)` | Callback for unicode input mode set, for users. |
|
||||
---
|
||||
|
||||
This feature can be used, for instance, to implement LED indicators for the current unicode input mode.
|
||||
### `void unicode_input_mode_step(void)` : id=api-unicode-input-mode-step
|
||||
|
||||
### Input Key Configuration
|
||||
Change to the next Unicode input mode.
|
||||
|
||||
You can customize the keys used to trigger Unicode input for macOS, Linux and WinCompose by adding corresponding defines to your `config.h`. The default values match the platforms' default settings, so you shouldn't need to change this unless Unicode input isn't working, or you want to use a different key (e.g. in order to free up left or right Alt).
|
||||
---
|
||||
|
||||
|Define |Type |Default |Example |
|
||||
|------------------|----------|------------------|-------------------------------------------|
|
||||
|`UNICODE_KEY_MAC` |`uint8_t` |`KC_LALT` |`#define UNICODE_KEY_MAC KC_RALT` |
|
||||
|`UNICODE_KEY_LNX` |`uint16_t`|`LCTL(LSFT(KC_U))`|`#define UNICODE_KEY_LNX LCTL(LSFT(KC_E))`|
|
||||
|`UNICODE_KEY_WINC`|`uint8_t` |`KC_RALT` |`#define UNICODE_KEY_WINC KC_RGUI` |
|
||||
### `void unicode_input_mode_step_reverse(void)` : id=api-unicode-input-mode-step-reverse
|
||||
|
||||
Change to the previous Unicode input mode.
|
||||
|
||||
## Sending Unicode Strings
|
||||
---
|
||||
|
||||
QMK provides several functions that allow you to send Unicode input to the host programmatically:
|
||||
### `void unicode_input_mode_set_user(uint8_t input_mode)` :id=api-unicode-input-mode-set-user
|
||||
|
||||
### `send_unicode_string()`
|
||||
User-level callback, invoked when the input mode is changed.
|
||||
|
||||
This function is much like `send_string()`, but it allows you to input UTF-8 characters directly. It supports all code points, provided the selected input mode also supports it. Make sure your `keymap.c` file is formatted using UTF-8 encoding.
|
||||
#### Arguments :id=api-unicode-input-mode-set-user-arguments
|
||||
|
||||
```c
|
||||
send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");
|
||||
```
|
||||
- `uint8_t input_mode`
|
||||
The new input mode.
|
||||
|
||||
Example uses include sending Unicode strings when a key is pressed, as described in [Macros](feature_macros.md).
|
||||
---
|
||||
|
||||
## Additional Language Support
|
||||
### `void unicode_input_mode_set_kb(uint8_t input_mode)` :id=api-unicode-input-mode-set-kb
|
||||
|
||||
In `quantum/keymap_extras`, you'll see various language files — these work the same way as the ones for alternative layouts such as Colemak or BÉPO. When you include one of these language headers, you gain access to keycodes specific to that language / national layout. Such keycodes are defined by a 2-letter country/language code, followed by an underscore and a 4-letter abbreviation of the character to which the key corresponds. For example, including `keymap_french.h` and using `FR_UGRV` in your keymap will output `ù` when typed on a system with a native French AZERTY layout.
|
||||
Keyboard-level callback, invoked when the input mode is changed.
|
||||
|
||||
If the primary system layout you use on your machine is different from US ANSI, using these language-specific keycodes can help your QMK keymaps better match what will actually be output on the screen. However, keep in mind that these keycodes are just aliases for the corresponding default US keycodes under the hood, and that the HID protocol used by keyboards is itself inherently based on US ANSI.
|
||||
#### Arguments :id=api-unicode-input-mode-set-kb-arguments
|
||||
|
||||
- `uint8_t input_mode`
|
||||
The new input mode.
|
||||
|
||||
## International Characters on Windows
|
||||
---
|
||||
|
||||
### AutoHotkey
|
||||
### `void unicode_input_start(void)` :id=api-unicode-input-start
|
||||
|
||||
The method does not require Unicode support in the keyboard itself but instead depends on [AutoHotkey](https://autohotkey.com) running in the background.
|
||||
Begin the Unicode input sequence. The exact behavior depends on the currently selected input mode:
|
||||
|
||||
First you need to select a modifier combination that is not in use by any of your programs.
|
||||
Ctrl+Alt+Win is not used very widely and should therefore be perfect for this.
|
||||
There is a macro defined for a mod-tab combo `LCAG_T`.
|
||||
Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`.
|
||||
This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key.
|
||||
- **macOS**: Hold `UNICODE_KEY_MAC`
|
||||
- **Linux**: Tap `UNICODE_KEY_LNX`
|
||||
- **WinCompose**: Tap `UNICODE_KEY_WINC`, then U
|
||||
- **HexNumpad**: Hold Left Alt, then tap Numpad +
|
||||
- **Emacs**: Tap Ctrl+X, then 8, then Enter
|
||||
|
||||
In the default script of AutoHotkey you can define custom hotkeys.
|
||||
This function is weakly defined, and can be overridden in user code.
|
||||
|
||||
<^<!<#a::Send, ä
|
||||
<^<!<#<+a::Send, Ä
|
||||
---
|
||||
|
||||
The hotkeys above are for the combination CtrlAltGui and CtrlAltGuiShift plus the letter a.
|
||||
AutoHotkey inserts the Text right of `Send, ` when this combination is pressed.
|
||||
### `void unicode_input_finish(void)` :id=api-unicode-input-finish
|
||||
|
||||
### 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 à.
|
||||
You can find details on how to enable this [here](https://support.microsoft.com/en-us/help/17424/windows-change-keyboard-layout).
|
||||
- **macOS**: Release `UNICODE_KEY_MAC`
|
||||
- **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:
|
||||
```
|
||||
key <AD04> { [ r, R, U1F923 ] };
|
||||
```
|
||||
- **macOS**: Release `UNICODE_KEY_MAC`
|
||||
- **Linux**: Tap Escape
|
||||
- **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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Word Per Minute (WPM) Calculcation
|
||||
# Word Per Minute (WPM) Calculation
|
||||
|
||||
The WPM feature uses time between keystrokes to compute a rolling average words per minute rate and makes this available for various uses.
|
||||
|
||||
|
@ -322,6 +322,29 @@ Flashing sequence:
|
||||
3. Flash a .bin file
|
||||
4. Reset the device into application mode (may be done automatically)
|
||||
|
||||
## WB32 DFU
|
||||
|
||||
Some keyboards produced for several commercial brands (GMMK, Akko, MonsGeek, Inland) use this bootloader. The `wb32-dfu-updater` utility is bundled with [QMK MSYS](https://msys.qmk.fm/) and [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide). If neither of these flashing methods is available for your OS, you will likely need to [compile the CLI version from source](https://github.com/WestberryTech/wb32-dfu-updater).
|
||||
|
||||
The `info.json` setting for this bootloader is `wb32-dfu`.
|
||||
|
||||
Compatible flashers:
|
||||
|
||||
* [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide) (recommended GUI)
|
||||
* [wb32-dfu-updater_cli](https://github.com/WestberryTech/wb32-dfu-updater) / `:flash` target in QMK (recommended command line)
|
||||
```
|
||||
wb32-dfu-updater_cli -t -s 0x8000000 -D <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
|
||||
|
||||
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.
|
||||
|
@ -109,7 +109,7 @@ This allows you to send Unicode characters using `UC(<code point>)` in your keym
|
||||
|
||||
`UNICODEMAP_ENABLE`
|
||||
|
||||
This allows you to send Unicode characters using `X(<map index>)` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
|
||||
This allows you to send Unicode characters using `UM(<map index>)` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
|
||||
|
||||
`UCIS_ENABLE`
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
# Vagrant Quick Start
|
||||
|
||||
This project includes a `Vagrantfile` that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
|
||||
|
||||
## Requirements
|
||||
|
||||
Using the `Vagrantfile` in this repository requires you have [Vagrant](https://www.vagrantup.com/) as well as a supported provider installed:
|
||||
|
||||
* [VirtualBox](https://www.virtualbox.org/) (Version at least 5.0.12)
|
||||
* Sold as 'the most accessible platform to use Vagrant'
|
||||
* [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](https://www.vagrantup.com/vmware)
|
||||
* The (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion
|
||||
* [Docker](https://www.docker.com/)
|
||||
|
||||
Other than having Vagrant, a suitable provider installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start an environment (either a virtual machine or container) that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
|
||||
|
||||
## Flashing the Firmware
|
||||
|
||||
The "easy" way to flash the firmware is using a tool from your host OS:
|
||||
|
||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox) (recommended)
|
||||
* [Teensy Loader](https://www.pjrc.com/teensy/loader.html)
|
||||
|
||||
If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.
|
||||
|
||||
## Vagrantfile Overview
|
||||
The development environment is configured to run the QMK Docker image, `qmkfm/qmk_cli`. This not only ensures predictability between systems, it also mirrors the CI environment.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why am I seeing issues under Virtualbox?
|
||||
Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12. **Alternately, you can try running the following command:**
|
||||
|
||||
```
|
||||
vagrant plugin install vagrant-vbguest
|
||||
```
|
||||
|
||||
### How do I remove an existing environment?
|
||||
Finished with your environment? From anywhere inside the folder where you checked out this project, Execute:
|
||||
|
||||
```
|
||||
vagrant destroy
|
||||
```
|
||||
|
||||
### What if I want to use Docker directly?
|
||||
Want to benefit from the Vagrant workflow without a virtual machine? The Vagrantfile is configured to bypass running a virtual machine, and run the container directly. Execute the following when bringing up the environment to force the use of Docker:
|
||||
```
|
||||
vagrant up --provider=docker
|
||||
```
|
||||
|
||||
### How do I access the virtual machine instead of the Docker container?
|
||||
Execute the following to bypass the `vagrant` user booting directly to the official qmk builder image:
|
||||
|
||||
```
|
||||
vagrant ssh -c 'sudo -i'
|
||||
```
|
@ -72,7 +72,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.
|
||||
|
||||
### I2Cv1 :id=i2cv1
|
||||
### I2Cv1 :id=arm-configuration-i2cv1
|
||||
|
||||
* STM32F1xx
|
||||
* STM32F2xx
|
||||
@ -88,7 +88,7 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#7_I2Cv1_con
|
||||
|`I2C1_CLOCK_SPEED` |`100000` |
|
||||
|`I2C1_DUTY_CYCLE` |`STD_DUTY_CYCLE`|
|
||||
|
||||
### I2Cv2 :id=i2cv2
|
||||
### I2Cv2 :id=arm-configuration-i2cv2
|
||||
|
||||
* STM32F0xx
|
||||
* STM32F3xx
|
||||
@ -105,9 +105,9 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#8_I2Cv2_I2C
|
||||
|`I2C1_TIMINGR_SCLH` |`38U` |
|
||||
|`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.
|
||||
|
||||
@ -126,28 +126,28 @@ void i2c_init(void) {
|
||||
|
||||
---
|
||||
|
||||
### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)`
|
||||
### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` :id=api-i2c-start
|
||||
|
||||
Start an I2C transaction.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-start-arguments
|
||||
|
||||
- `uint8_t address`
|
||||
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-i2c-start-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_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)`
|
||||
### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
|
||||
|
||||
Send multiple bytes to the selected I2C device.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-transmit-arguments
|
||||
|
||||
- `uint8_t address`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -158,17 +158,17 @@ Send multiple bytes to the selected I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### 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)`
|
||||
### `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
|
||||
#### Arguments :id=api-i2c-receive-arguments
|
||||
|
||||
- `uint8_t address`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -179,17 +179,17 @@ Receive multiple bytes from the selected I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### 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_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||
### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-writereg
|
||||
|
||||
Writes to a register with an 8-bit address on the I2C device.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-writereg-arguments
|
||||
|
||||
- `uint8_t devaddr`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -202,17 +202,17 @@ Writes to a register with an 8-bit address on the I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-i2c-writereg-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_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||
### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-writereg16
|
||||
|
||||
Writes to a register with a 16-bit address (big endian) on the I2C device.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-writereg16-arguments
|
||||
|
||||
- `uint8_t devaddr`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -225,17 +225,17 @@ Writes to a register with a 16-bit address (big endian) on the I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-i2c-writereg16-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_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
|
||||
### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-readreg
|
||||
|
||||
Reads from a register with an 8-bit address on the I2C device.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-readreg-arguments
|
||||
|
||||
- `uint8_t devaddr`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -246,7 +246,7 @@ Reads from a register with an 8-bit address on the I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-i2c-readreg-return
|
||||
|
||||
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
|
||||
|
||||
@ -256,7 +256,7 @@ Reads from a register with an 8-bit address on the I2C device.
|
||||
|
||||
Reads from a register with a 16-bit address (big endian) on the I2C device.
|
||||
|
||||
#### Arguments
|
||||
#### Arguments :id=api-i2c-readreg16-arguments
|
||||
|
||||
- `uint8_t devaddr`
|
||||
The 7-bit I2C address of the device.
|
||||
@ -267,12 +267,12 @@ Reads from a register with a 16-bit address (big endian) on the I2C device.
|
||||
- `uint16_t timeout`
|
||||
The time in milliseconds to wait for a response from the target device.
|
||||
|
||||
#### Return Value
|
||||
#### Return Value :id=api-i2c-readreg16-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_stop(void)`
|
||||
### `i2c_status_t i2c_stop(void)` :id=api-i2c-stop
|
||||
|
||||
Stop the current I2C transaction.
|
||||
|
@ -35,6 +35,40 @@ To use a 5V/16MHz Pro Micro as an ISP flashing tool, you will first need to load
|
||||
|
||||
!> Note that the `10` pin on the Pro Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Pro Micro to the `RESET` on the keyboard.
|
||||
|
||||
|
||||
### Arduino Uno / Micro as ISP
|
||||
|
||||
[Arduino Uno](https://store.arduino.cc/products/arduino-uno-rev3)
|
||||
[Arduino Micro](https://store.arduino.cc/products/arduino-micro)
|
||||
|
||||
A standard Uno or Micro can be used as an ISP flashing tool using the [example "ArduinoISP" sketch](https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP#load-the-sketch) to emulate an STK500 ISP. Also works with Sparkfun Pro Micros and clones.
|
||||
|
||||
**AVRDUDE Programmer**: `stk500v1`
|
||||
**AVRDUDE Port**: Serial
|
||||
|
||||
#### Wiring
|
||||
|
||||
|Uno |Keyboard|
|
||||
|-----------|--------|
|
||||
|`5V` |`VCC` |
|
||||
|`GND` |`GND` |
|
||||
|`10` (`B2`)|`RESET` |
|
||||
|`13` (`B5`)|`SCLK` |
|
||||
|`11` (`B3`)|`MOSI` |
|
||||
|`12` (`B4`)|`MISO` |
|
||||
|
||||
|Micro |Keyboard|
|
||||
|-----------|--------|
|
||||
|`5V` |`VCC` |
|
||||
|`GND` |`GND` |
|
||||
|`10` (`B6`)|`RESET` |
|
||||
|`15` (`B1`)|`SCLK` |
|
||||
|`16` (`B2`)|`MOSI` |
|
||||
|`14` (`B3`)|`MISO` |
|
||||
|
||||
!> Note that the `10` pin on the Uno/Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Uno/Micro to the `RESET` on the keyboard.
|
||||
|
||||
|
||||
### Teensy 2.0 as ISP
|
||||
|
||||
[PJRC Teensy 2.0](https://www.pjrc.com/store/teensy.html)
|
||||
@ -57,6 +91,7 @@ To use a Teensy 2.0 as an ISP flashing tool, you will first need to load a [spec
|
||||
|
||||
!> Note that the `B0` pin on the Teensy should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Teensy to the `RESET` on the keyboard.
|
||||
|
||||
|
||||
### SparkFun PocketAVR / USBtinyISP
|
||||
|
||||
[SparkFun PocketAVR](https://www.sparkfun.com/products/9825)
|
||||
|
@ -38,7 +38,6 @@
|
||||
* [キーマップの概要](ja/keymap.md)
|
||||
* 開発環境
|
||||
* [Docker のガイド](ja/getting_started_docker.md)
|
||||
* [Vagrant のガイド](ja/getting_started_vagrant.md)
|
||||
* 書き込み
|
||||
* [書き込み](ja/flashing.md)
|
||||
* [ATmega32A の書き込み (ps2avrgb)](ja/flashing_bootloadhid.md)
|
||||
@ -69,6 +68,7 @@
|
||||
* [モッドタップ](ja/mod_tap.md)
|
||||
* [マクロ](ja/feature_macros.md)
|
||||
* [マウスキー](ja/feature_mouse_keys.md)
|
||||
* [Repeat Key](ja/feature_repeat_key.md)
|
||||
* [Space Cadet Shift](ja/feature_space_cadet.md)
|
||||
* [US ANSI シフトキー](ja/keycodes_us_ansi_shifted.md)
|
||||
|
||||
|
@ -159,9 +159,6 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* 詳細は [Permissive Hold](ja/tap_hold.md#permissive-hold) を見てください
|
||||
* `#define PERMISSIVE_HOLD_PER_KEY`
|
||||
* キーごとの `PERMISSIVE_HOLD` 設定の処理を有効にします
|
||||
* `#define IGNORE_MOD_TAP_INTERRUPT`
|
||||
* 両方のキーに `TAPPING_TERM` を適用することで、ホールド時に他のキーに変換するキーを使ってローリングコンボ (zx) をすることができるようにします
|
||||
* 詳細は [Ignore Mod Tap Interrupt](ja/tap_hold.md#ignore-mod-tap-interrupt) を見てください
|
||||
* `#define TAPPING_FORCE_HOLD`
|
||||
* タップされた直後に、デュアルロールキーを修飾子として使用できるようにします
|
||||
* [Tapping Force Hold](ja/tap_hold.md#tapping-force-hold)を見てください
|
||||
@ -179,8 +176,6 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* ワンショットがタイムアウトするまでの時間
|
||||
* `#define ONESHOT_TAP_TOGGLE 2`
|
||||
* ワンショットトグルが引き起こされるまでのタップ数
|
||||
* `#define COMBO_COUNT 2`
|
||||
* [コンボ](ja/feature_combo.md)機能で使っているコンボの数にこれを設定します。
|
||||
* `#define COMBO_TERM 200`
|
||||
* コンボキーが検出されるまでの時間。定義されていない場合は、デフォルトは `TAPPING_TERM` です。
|
||||
* `#define TAP_CODE_DELAY 100`
|
||||
|
@ -109,8 +109,8 @@ QMK が完全な `info.json` を生成するときはいつでも、`config.h`
|
||||
パズルの最後のピースは、ビルドシステムに新しいオプションを提供することです。
|
||||
これは、2つのファイルを生成することによって行われます。
|
||||
|
||||
* `.build/obj_<keyboard>/src/info_config.h`
|
||||
* `.build/obj_<keyboard>/src/rules.mk`
|
||||
* `.build/obj_<keyboard>_<keymap>/src/info_config.h`
|
||||
* `.build/obj_<keyboard>_<keymap>/src/rules.mk`
|
||||
|
||||
この2つのファイルは、次のコードによって生成されます。
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
```c
|
||||
const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END};
|
||||
combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)};
|
||||
combo_t key_combos[] = {COMBO(test_combo, KC_ESC)};
|
||||
```
|
||||
|
||||
これは、A と B のキーを押した場合に、"Escape" を送信します。
|
||||
@ -38,7 +38,7 @@ enum combos {
|
||||
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
|
||||
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
|
||||
|
||||
combo_t key_combos[COMBO_COUNT] = {
|
||||
combo_t key_combos[] = {
|
||||
[AB_ESC] = COMBO(ab_combo, KC_ESC),
|
||||
[JK_TAB] = COMBO(jk_combo, KC_TAB)
|
||||
};
|
||||
@ -55,7 +55,7 @@ enum combo_events {
|
||||
const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END};
|
||||
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};
|
||||
|
||||
combo_t key_combos[COMBO_COUNT] = {
|
||||
combo_t key_combos[] = {
|
||||
[ZC_COPY] = COMBO_ACTION(copy_combo),
|
||||
[XV_PASTE] = COMBO_ACTION(paste_combo),
|
||||
};
|
||||
|
@ -64,7 +64,7 @@ QMK はその場で作られた一時的なマクロをサポートします。
|
||||
|
||||
direction がどのマクロであるかを示すことに注意してください。`1` がマクロ 1、`-1` がマクロ 2、0 がマクロ無しです。
|
||||
|
||||
* `dynamic_macro_record_start_user(void)` - マクロの記録を開始する時に起動されます。
|
||||
* `dynamic_macro_record_start_user(int8_t direction)` - マクロの記録を開始する時に起動されます。
|
||||
* `dynamic_macro_play_user(int8_t direction)` - マクロを再生する時に起動されます。
|
||||
* `dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record)` - マクロの記録中に各キー押下で起動されます。
|
||||
* `dynamic_macro_record_end_user(int8_t direction)` - マクロの記録を停止した時に起動されます。
|
||||
|
@ -80,7 +80,7 @@ bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
|
||||
bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed);
|
||||
```
|
||||
|
||||
この関数はキーが処理された後、ただしコードを送信するかどうかを決める前に呼び出されます。`IS_PRESSED(record->event)` が false で、`pressed` が 0 または 1 の場合は、コードはまもなく送信されますが、まだ送信されてはいません。ここが速記コードあるいはキーのライブ表示などのフックを配置する場所です。
|
||||
この関数はキーが処理された後、ただしコードを送信するかどうかを決める前に呼び出されます。`record->event.pressed` が false で、`pressed` が 0 または 1 の場合は、コードはまもなく送信されますが、まだ送信されてはいません。ここが速記コードあるいはキーのライブ表示などのフックを配置する場所です。
|
||||
|
||||
|
||||
## キーコードリファレンス :id=keycode-reference
|
||||
|
@ -1,61 +0,0 @@
|
||||
# Vagrant クイックスタート
|
||||
|
||||
<!---
|
||||
original document: 0.12.43:docs/getting_started_vagrant.md
|
||||
git diff 0.12.43 HEAD -- docs/getting_started_vagrant.md | cat
|
||||
-->
|
||||
|
||||
このプロジェクトは、プライマリオペレーティングシステムに大きな変更を加えることなくキーボードの新しいファームウェアを非常に簡単に構築することができる `Vagrantfile` を含みます。これは、あなたがプロジェクトをクローンしビルドを実行した時に、ビルドのために Vagrantfile を使っている他のユーザと全く同じ環境を持つことも保証します。これにより、人々はあなたが遭遇した問題の解決をより簡単に行えるようになります。
|
||||
|
||||
## 必要事項
|
||||
|
||||
このリポジトリ内の `Vagrantfile` を使うには、[Vagrant](https://www.vagrantup.com/) およびサポートされるプロバイダがインストールされている必要があります:
|
||||
|
||||
* [VirtualBox](https://www.virtualbox.org/) (バージョン 5.0.12 以降)
|
||||
* 「Vagrant を使うために最もアクセスしやすいプラットフォーム」とうたわれています。
|
||||
* [VMware Workstation](https://www.vmware.com/products/workstation) および [Vagrant VMware プラグイン](https://www.vagrantup.com/vmware)
|
||||
* (有料) VMware プラグインには、ライセンスされた VMware Workstation/Fusion のコピーが必要です。
|
||||
* [Docker](https://www.docker.com/)
|
||||
|
||||
Vagrant 以外に、適切なプロバイダがインストールされ、その後におそらくコンピュータを再起動すると、このプロジェクトをチェックアウトしたフォルダ内の任意の場所で 'vagrant up' を単純に実行することができ、このプロジェクトをビルドするのに必要な全てのツールが含まれる環境(仮想マシンあるいはコンテナ)が開始されます。Vagrant 起動時にうまく始めるためのヒントが表示されますが、それ以外に、以下のビルドドキュメントを参照することもできます。
|
||||
|
||||
## ファームウェアの書き込み
|
||||
|
||||
ファームウェアを書き込む「簡単な」方法は、ホスト OS からツールを使うことです:
|
||||
|
||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox) (推奨)
|
||||
* [Teensy ローダー](https://www.pjrc.com/teensy/loader.html)
|
||||
|
||||
コマンドラインでプログラムしたい場合は、Vagranfile の ['modifyvm'] 行のコメントを解除して Linux への USB パススルーを有効にし、dfu-util/dfu-programmer のようなコマンドラインツールを使ってプログラムすることができます。あるいは Teensy CLI バージョンをインストールすることができます。
|
||||
|
||||
## Vagrantfile の概要
|
||||
開発環境は QMK Docker イメージ、`qmkfm/qmk_cli` を実行するように設定されています。これはシステム間の予測可能性が保証されるだけでなく、CI 環境もミラーされます。
|
||||
|
||||
## FAQ
|
||||
|
||||
### Virtualbox で問題が発生するのはなぜですか?
|
||||
Virtualbox 5 の特定のバージョンはこの Vagrantfile のボックスにインストールされている Virtualbox の拡張機能と互換性が無いようです。/vagrant のマウントで問題が発生した場合は、Virtualbox のバージョンを少なくとも 5.0.12 にアップグレードしてください。**または、以下のコマンドを実行してみることができます:**
|
||||
|
||||
```console
|
||||
vagrant plugin install vagrant-vbguest
|
||||
```
|
||||
|
||||
### 既存の環境を削除するにはどうすればいいですか?
|
||||
あなたの環境での作業が完了しましたか?このプロジェクトをチェックアウトしたフォルダの中のどこからでも、以下を実行してください:
|
||||
|
||||
```console
|
||||
vagrant destroy
|
||||
```
|
||||
|
||||
### Docker を直接使いたい場合はどうしますか?
|
||||
仮想マシン無しで Vagrant のワークフローを活用したいですか?Vagrantfile は仮想マシンの実行をバイパスし、コンテナを直接実行するように設定されています。Docker を強制的に使うように環境を立ち上げる場合は、以下を実行してください:
|
||||
```console
|
||||
vagrant up --provider=docker
|
||||
```
|
||||
|
||||
### Docker コンテナではなく仮想マシンにアクセスするにはどうすればいいですか?
|
||||
以下を実行して、公式の QMK ビルダーイメージから直接起動する `vagrant` ユーザをバイパスするようにします:
|
||||
|
||||
```console
|
||||
vagrant ssh -c 'sudo -i'
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user