Compare commits

..

19 Commits

Author SHA1 Message Date
skullY
8b4d28f6fb Fix omnikeyish 2020-02-29 21:35:30 -08:00
skullY
6506745502 Fix model01 2020-02-29 21:35:30 -08:00
skullY
a18f85c6b6 fix matrix/noah 2020-02-29 21:35:30 -08:00
skullY
0ef12b059d fix maartenwut/minitomic 2020-02-29 21:35:30 -08:00
skullY
b8d54bddcc Fix k_type 2020-02-29 21:35:30 -08:00
skullY
a84bc86073 Fix hub16 2020-02-29 21:35:29 -08:00
skullY
a17fe1f2ad fix handwired/prime_exl_plus 2020-02-29 21:35:29 -08:00
skullY
7ab1e6d0f0 fix flx/virgo 2020-02-29 21:35:29 -08:00
skullY
c4001ca425 fix ergodox_infinity 2020-02-29 21:35:29 -08:00
skullY
ac8a8e838e fix bpiphany/pegasushoof/2015 2020-02-29 21:35:29 -08:00
skullY
5ba8a76da5 wip 2020-02-29 21:35:29 -08:00
skullY
b281d88c6f update the template too 2020-02-29 21:35:29 -08:00
skullY
123758c663 wip 2020-02-29 21:35:29 -08:00
skullY
0d8b4d6fa6 Ensure more _user functions will always run 2020-02-29 21:35:29 -08:00
skullY
256fabca9e wip 2020-02-29 21:35:28 -08:00
skullY
2d64301cd9 run the _user functions whenever we run the _kb functions 2020-02-29 21:34:46 -08:00
skullY
69b2a82be6 change the order to match the in situ assumption by keyboard maintainers 2020-02-29 21:34:46 -08:00
skullY
ff49927703 Fix the process_record_kb weak function too. h/t @fauxpark. 2020-02-29 21:34:46 -08:00
skullY
c4aa18363e wip 2020-02-29 21:34:46 -08:00
11703 changed files with 194094 additions and 460769 deletions

24
.clang_complete Normal file
View File

@@ -0,0 +1,24 @@
-I.
-I./drivers
-I./drivers/avr
-I./keyboards/ergodox_ez
-I./keyboards/ergodox_ez/keymaps/vim
-I./lib
-I./lib/lufa
-I./quantum
-I./quantum/api
-I./quantum/audio
-I./quantum/keymap_extras
-I./quantum/process_keycode
-I./quantum/serial_link
-I./quantum/template
-I./quantum/tools
-I./quantum/visualizer
-I./tmk_core
-I./tmk_core/common
-I./tmk_core/common/debug.h
-I./tmk_core/protocol
-I./tmk_core/protocol/lufa
-I./util
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\"

View File

@@ -26,8 +26,7 @@
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My code follows the code style of this project: [**C**](https://docs.qmk.fm/#/coding_conventions_c), [**Python**](https://docs.qmk.fm/#/coding_conventions_python)
- [ ] I have read the [**PR Checklist** document](https://docs.qmk.fm/#/pr_checklist) and have made the appropriate changes.
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the [**CONTRIBUTING** document](https://docs.qmk.fm/#/contributing).

42
.github/labeler.yml vendored
View File

@@ -1,42 +0,0 @@
core:
- quantum/**/*
- tmk_core/**/*
- drivers/**/*
- tests/**/*
- util/**/*
- platforms/**/*
- Makefile
- '*.mk'
dependencies:
- any:
- 'lib/**/*'
- '!lib/python/**/*'
keyboard:
- any:
- 'keyboards/**/*'
- '!keyboards/**/keymaps/**/*'
keymap:
- users/**/*
- layouts/**/*
- keyboards/**/keymaps/**/*
via:
- keyboards/**/keymaps/via/*
cli:
- bin/qmk
- requirements.txt
- lib/python/**/*
python:
- '**/*.py'
documentation:
- docs/**/*
translation:
- docs/fr-fr/**/*
- docs/es/**/*
- docs/ja/**/*
- docs/he-il/**/*
- docs/pt-br/**/*
- docs/zh-cn/**/*
- docs/de/**/*
- docs/ru-ru/**/*
CI:
- .github/**/*

View File

@@ -1,42 +0,0 @@
name: Update API Data
on:
push:
branches:
- master
paths:
- 'keyboards/**'
- 'layouts/community/**'
jobs:
api_data:
runs-on: ubuntu-latest
container: qmkfm/base_container
# protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
persist-credentials: false
- name: Generate API Data
run: qmk generate-api
- name: Install rsync
run: |
apt-get update && apt-get install -y rsync
- name: Upload API Data
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
ACCESS_TOKEN: ${{ secrets.API_TOKEN_GITHUB }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: main
FOLDER: api_data/v1
CLEAN: true
GIT_CONFIG_EMAIL: hello@qmk.fm
REPOSITORY_NAME: qmk/qmk_keyboards
TARGET_FOLDER: v1

View File

@@ -1,33 +0,0 @@
name: Essential files modified
on:
push:
branches:
- master
paths:
- quantum/**/*
- tmk_core/**/*
- drivers/**/*
- tests/**/*
- util/**/*
- platforms/**/*
- Makefile
- '*.mk'
jobs:
tag:
runs-on: ubuntu-latest
# protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Bump version and push tag
uses: anothrNick/github-tag-action@1.26.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEFAULT_BUMP: 'patch'

View File

@@ -19,7 +19,7 @@ jobs:
container: qmkfm/base_container
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v1
with:
submodules: recursive
- name: Install dependencies

View File

@@ -1,42 +0,0 @@
name: Update Develop API Data
on:
push:
branches:
- develop
paths:
- 'keyboards/**'
- 'layouts/community/**'
jobs:
api_data:
runs-on: ubuntu-latest
container: qmkfm/base_container
# protect against those who work in their fork on develop
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
persist-credentials: false
- name: Generate API Data
run: qmk generate-api
- name: Install rsync
run: |
apt-get update && apt-get install -y rsync
- name: Upload API Data
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
ACCESS_TOKEN: ${{ secrets.API_TOKEN_GITHUB }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: main
FOLDER: api_data/v1
CLEAN: true
GIT_CONFIG_EMAIL: hello@qmk.fm
REPOSITORY_NAME: qmk/qmk_keyboards_devel
TARGET_FOLDER: v1

View File

@@ -1,37 +0,0 @@
name: Update develop after master merge
on:
push:
branches:
- master
jobs:
develop_update:
runs-on: ubuntu-latest
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Checkout develop
run: |
git fetch origin master develop
git checkout develop
- name: Check if branch locked
id: check_locked
uses: andstor/file-existence-action@v1
with:
files: ".locked"
- name: Update develop from master
if: steps.check_locked.outputs.files_exists == 'false'
run: |
git config --global user.name "QMK Bot"
git config --global user.email "hello@qmk.fm"
git merge origin/master
git push origin develop

View File

@@ -1,43 +0,0 @@
name: Generate Docs
on:
push:
branches:
- master
paths:
- 'tmk_core/**'
- 'quantum/**'
- 'platforms/**'
- 'docs/**'
- '.github/workflows/docs.yml'
jobs:
generate:
runs-on: ubuntu-latest
container: qmkfm/base_container
# protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Install dependencies
run: |
apt-get update && apt-get install -y rsync nodejs npm doxygen
npm install -g moxygen
- name: Build docs
run: |
qmk --verbose generate-docs
- name: Deploy
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_BRANCH: master
BRANCH: gh-pages
FOLDER: .build/docs
GIT_CONFIG_EMAIL: hello@qmk.fm

View File

@@ -1,37 +0,0 @@
name: Format Codebase
on:
push:
branches:
- master
jobs:
format:
runs-on: ubuntu-latest
container: qmkfm/base_container
# protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.API_TOKEN_GITHUB }}
- name: Install dependencies
run: |
apt-get update && apt-get install -y dos2unix
- name: Format files
run: |
bin/qmk cformat -a
bin/qmk pyformat
bin/qmk fileformat
- name: Commit files
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Format code according to conventions for $GITHUB_SHA
commit_user_name: QMK Bot
commit_user_email: hello@qmk.fm
commit_author: QMK Bot <hello@qmk.fm>

View File

@@ -1,14 +0,0 @@
name: "Pull Request Labeler"
on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, locked]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: '.github/labeler.yml'

View File

@@ -1,55 +0,0 @@
name: PR Lint keyboards
on:
pull_request:
paths:
- 'keyboards/**'
jobs:
lint:
runs-on: ubuntu-latest
container: qmkfm/base_container
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: trilom/file-changes-action@v1.2.4
id: file_changes
with:
output: '\n'
- name: Print info
run: |
git rev-parse --short HEAD
echo ${{ github.event.pull_request.base.sha }}
echo '${{ steps.file_changes.outputs.files}}'
- name: Run qmk lint
shell: 'bash {0}'
run: |
QMK_CHANGES=$(echo -e '${{ steps.file_changes.outputs.files}}')
QMK_KEYBOARDS=$(qmk list-keyboards)
exit_code=0
for KB in $QMK_KEYBOARDS; do
KEYBOARD_CHANGES=$(echo "$QMK_CHANGES" | grep -E '^(keyboards/'${KB}'/)')
if [[ -z "$KEYBOARD_CHANGES" ]]; then
# skip as no changes for this keyboard
continue
fi
KEYMAP_ONLY=$(echo "$KEYBOARD_CHANGES" | grep -cv /keymaps/)
if [[ $KEYMAP_ONLY -gt 0 ]]; then
echo "linting ${KB}"
qmk lint --keyboard ${KB} && qmk info -l --keyboard ${KB}
exit_code=$(($exit_code + $?))
fi
done
if [[ $exit_code -gt 255 ]]; then
exit 255
fi
exit $exit_code

6
.gitignore vendored
View File

@@ -16,7 +16,6 @@
*.swp
tags
*~
api_data/v1
build/
.build/
*.bak
@@ -25,7 +24,6 @@ quantum/version.h
.idea/
CMakeLists.txt
cmake-build-debug
.clang_complete
doxygen/
.DS_Store
/util/wsl_downloaded
@@ -49,6 +47,7 @@ doxygen/
*.iml
.browse.VC.db*
*.stackdump
util/Win_Check_Output.txt
# Let these ones be user specific, since we have so many different configurations
.vscode/c_cpp_properties.json
.vscode/launch.json
@@ -74,6 +73,3 @@ __pycache__
# prerequisites for updating ChibiOS
/util/fmpp*
# Allow to exist but don't include it in the repo
user_song_list.h

8
.gitmodules vendored
View File

@@ -12,13 +12,7 @@
branch = master
[submodule "lib/googletest"]
path = lib/googletest
url = https://github.com/qmk/googletest
url = https://github.com/google/googletest
[submodule "lib/lufa"]
path = lib/lufa
url = https://github.com/qmk/lufa
[submodule "lib/vusb"]
path = lib/vusb
url = https://github.com/qmk/v-usb
[submodule "lib/printf"]
path = lib/printf
url = https://github.com/qmk/printf

View File

@@ -18,15 +18,20 @@ addons:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
packages:
- pandoc
- diffutils
- dos2unix
- doxygen
- clang-format-7
- libstdc++-7-dev
install:
- npm install -g moxygen
script:
- git fetch --depth=50 origin $TRAVIS_BRANCH:$TRAVIS_BRANCH
- git rev-parse --short HEAD
- git diff --name-only HEAD $TRAVIS_BRANCH
- bash util/travis_test.sh
- bash util/travis_build.sh
- bash util/travis_docs.sh
after_script:
bash util/travis_compiled_push.sh
notifications:

20
.vscode/settings.json vendored
View File

@@ -9,18 +9,12 @@
"**/*.bin": true
},
"files.associations": {
"*.h": "c",
"*.c": "c",
"*.inc": "c",
"*.cpp": "cpp",
"*.hpp": "cpp",
"xstddef": "c",
"type_traits": "c",
"utility": "c",
"ranges": "c"
},
"[markdown]": {
"editor.trimAutoWhitespace": false,
"files.trimTrailingWhitespace": false
"*.h": "c",
"*.c": "c",
"*.cpp": "cpp",
"*.hpp": "cpp",
"xstddef": "c",
"type_traits": "c",
"utility": "c"
}
}

144
Makefile
View File

@@ -29,9 +29,6 @@ $(info QMK Firmware $(QMK_VERSION))
endif
endif
# avoid 'Entering|Leaving directory' messages
MAKEFLAGS += --no-print-directory
ON_ERROR := error_occurred=1
BREAK_ON_ERRORS = no
@@ -68,15 +65,71 @@ PATH_ELEMENTS := $(subst /, ,$(STARTING_DIR))
# Initialize the path elements list for further processing
$(eval $(call NEXT_PATH_ELEMENT))
# This function sets the KEYBOARD; KEYMAP and SUBPROJECT to the correct
# variables depending on which directory you stand in.
# It's really a very simple if else chain, if you squint enough,
# but the makefile syntax makes it very verbose.
# If we are in a subfolder of keyboards
#
# *** No longer needed **
#
# ifeq ($(CURRENT_PATH_ELEMENT),keyboards)
# $(eval $(call NEXT_PATH_ELEMENT))
# KEYBOARD := $(CURRENT_PATH_ELEMENT)
# $(eval $(call NEXT_PATH_ELEMENT))
# # If we are in a subfolder of keymaps, or in other words in a keymap
# # folder
# ifeq ($(CURRENT_PATH_ELEMENT),keymaps)
# $(eval $(call NEXT_PATH_ELEMENT))
# KEYMAP := $(CURRENT_PATH_ELEMENT)
# # else if we are not in the keyboard folder itself
# else ifneq ($(CURRENT_PATH_ELEMENT),)
# # the we can assume it's a subproject, as no other folders
# # should have make files in them
# SUBPROJECT := $(CURRENT_PATH_ELEMENT)
# $(eval $(call NEXT_PATH_ELEMENT))
# # if we are inside a keymap folder of a subproject
# ifeq ($(CURRENT_PATH_ELEMENT),keymaps)
# $(eval $(call NEXT_PATH_ELEMENT))
# KEYMAP := $(CURRENT_PATH_ELEMENT)
# endif
# endif
# endif
define GET_KEYBOARDS
ifndef ALT_GET_KEYBOARDS
All_RULES_MK := $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/rules.mk))
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/*/rules.mk))
KEYMAPS_MK := $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/keymaps/*/rules.mk))
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/*/keymaps/*/rules.mk))
KEYBOARDS := $$(sort $$(filter-out $$(KEYMAPS_MK), $$(All_RULES_MK)))
else
KEYBOARDS := $(shell find keyboards/ -type f -iname "rules.mk" | grep -v keymaps | sed 's!keyboards/\(.*\)/rules.mk!\1!' | sort | uniq)
endif
endef
$(eval $(call GET_KEYBOARDS))
# Only consider folders with makefiles, to prevent errors in case there are extra folders
#KEYBOARDS += $(patsubst $(ROOD_DIR)/keyboards/%/rules.mk,%,$(wildcard $(ROOT_DIR)/keyboards/*/*/rules.mk))
# Phony targets to enable a few simple make commands outside the main processing below.
.PHONY: list-keyboards
list-keyboards:
util/list_keyboards.sh | sort -u | tr '\n' ' '
echo $(KEYBOARDS)
define PRINT_KEYBOARD
$(info $(PRINTING_KEYBOARD))
endef
.PHONY: generate-keyboards-file
generate-keyboards-file:
util/list_keyboards.sh | sort -u
$(foreach PRINTING_KEYBOARD,$(KEYBOARDS),$(eval $(call PRINT_KEYBOARD)))
.PHONY: clean
clean:
@@ -102,6 +155,8 @@ endif
# Uncomment these for debugging
# $(info Keyboard: $(KEYBOARD))
# $(info Keymap: $(KEYMAP))
# $(info Subproject: $(SUBPROJECT))
# $(info Keyboards: $(KEYBOARDS))
# Set the default goal depending on where we are running make from
@@ -159,6 +214,7 @@ endef
# A recursive helper function for finding the longest match
# $1 The list to be checked
# It works by always removing the currently matched item from the list
# and call itself recursively, until a match is found
define TRY_TO_MATCH_RULE_FROM_LIST_HELPER2
# Stop the recursion when the list is empty
ifneq ($1,)
@@ -213,29 +269,16 @@ endef
define PARSE_RULE
RULE := $1
COMMANDS :=
REQUIRE_PLATFORM_KEY :=
# If the rule starts with all, then continue the parsing from
# PARSE_ALL_KEYBOARDS
ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all),true)
KEYBOARD_RULE=all
$$(eval $$(call PARSE_ALL_KEYBOARDS))
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-avr),true)
KEYBOARD_RULE=all
REQUIRE_PLATFORM_KEY := avr
$$(eval $$(call PARSE_ALL_KEYBOARDS))
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-chibios),true)
KEYBOARD_RULE=all
REQUIRE_PLATFORM_KEY := chibios
$$(eval $$(call PARSE_ALL_KEYBOARDS))
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-arm_atsam),true)
KEYBOARD_RULE=all
REQUIRE_PLATFORM_KEY := arm_atsam
$$(eval $$(call PARSE_ALL_KEYBOARDS))
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,test),true)
$$(eval $$(call PARSE_TEST))
# If the rule starts with the name of a known keyboard, then continue
# the parsing from PARSE_KEYBOARD
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(shell util/list_keyboards.sh | sort -u)),true)
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(KEYBOARDS)),true)
KEYBOARD_RULE=$$(MATCHED_ITEM)
$$(eval $$(call PARSE_KEYBOARD,$$(MATCHED_ITEM)))
# Otherwise use the KEYBOARD variable, which is determined either by
@@ -248,8 +291,8 @@ define PARSE_RULE
$$(info | QMK's make format recently changed to use folder locations and colons:)
$$(info | make project_folder:keymap[:target])
$$(info | Examples:)
$$(info | make dz60:default)
$$(info | make planck/rev6:default:flash)
$$(info | make planck/rev4:default:dfu)
$$(info | make planck:default)
$$(info |)
endif
endef
@@ -352,9 +395,26 @@ endef
# if we are going to compile all keyboards, match the rest of the rule
# for each of them
define PARSE_ALL_KEYBOARDS
$$(eval $$(call PARSE_ALL_IN_LIST,PARSE_KEYBOARD,$(shell util/list_keyboards.sh noci | sort -u)))
$$(eval $$(call PARSE_ALL_IN_LIST,PARSE_KEYBOARD,$(KEYBOARDS)))
endef
# $1 Subproject
# When entering this, the keyboard and subproject are known, so now we need
# to determine which keymaps are going to get compiled
# define PARSE_SUBPROJECT
# endef
# If we want to parse all subprojects, but the keyboard doesn't have any,
# then use defaultsp instead
# define PARSE_ALL_SUBPROJECTS
# ifeq ($$(SUBPROJECTS),)
# $$(eval $$(call PARSE_SUBPROJECT,defaultsp))
# else
# $$(eval $$(call PARSE_ALL_IN_LIST,PARSE_SUBPROJECT,$$(SUBPROJECTS)))
# endif
# endef
# Prints a list of all known keymaps for the given keyboard
define LIST_ALL_KEYMAPS
COMMAND_true_LIST_KEYMAPS := \
@@ -384,7 +444,7 @@ define PARSE_KEYMAP
# Format it in bold
KB_SP := $(BOLD)$$(KB_SP)$(NO_COLOR)
# Specify the variables that we are passing forward to submake
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY)
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM)
# And the first part of the make command
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_keyboard.mk $$(MAKE_TARGET)
# The message to display
@@ -403,8 +463,6 @@ define BUILD
LOG=$$$$($$(MAKE_CMD) $$(MAKE_VARS) SILENT=true 2>&1) ; \
if [ $$$$? -gt 0 ]; \
then $$(PRINT_ERROR_PLAIN); \
elif [ "$$$$LOG" = "skipped" ] ; \
then $$(PRINT_SKIPPED_PLAIN); \
elif [ "$$$$LOG" != "" ] ; \
then $$(PRINT_WARNING_PLAIN); \
else \
@@ -496,21 +554,19 @@ if [ $$error_occurred -gt 0 ]; then $(HANDLE_ERROR); fi;
endef
# Catch everything and parse the command line ourselves.
# Let's match everything, we handle all the rule parsing ourselves
.PHONY: %
%:
# Check if we have the CMP tool installed
cmp $(ROOT_DIR)/Makefile $(ROOT_DIR)/Makefile >/dev/null 2>&1; if [ $$? -gt 0 ]; then printf "$(MSG_NO_CMP)"; exit 1; fi;
# Ensure that bin/qmk works.
if ! bin/qmk hello 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; exit 1; fi
# Ensure that python3 is installed. This check can be removed after python is used in more places.
if ! python3 --version 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; fi
# Check if the submodules are dirty, and display a warning if they are
ifndef SKIP_GIT
if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi
if [ ! -e lib/chibios-contrib ]; then git submodule sync lib/chibios-contrib && git submodule update --depth 50 --init lib/chibios-contrib; fi
if [ ! -e lib/ugfx ]; then git submodule sync lib/ugfx && git submodule update --depth 50 --init lib/ugfx; fi
if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
if [ ! -e lib/vusb ]; then git submodule sync lib/vusb && git submodule update --depth 50 --init lib/vusb; fi
if [ ! -e lib/printf ]; then git submodule sync lib/printf && git submodule update --depth 50 --init lib/printf; fi
git submodule status --recursive 2>/dev/null | \
while IFS= read -r x; do \
case "$$x" in \
@@ -532,6 +588,25 @@ endif
$(foreach TEST,$(sort $(TESTS)),$(RUN_TEST))
if [ -f $(ERROR_FILE) ]; then printf "$(MSG_ERRORS)" & exit 1; fi;
# These no longer work because of the colon system
# All should compile everything
# .PHONY: all
# all: all-keyboards test-all
# Define some shortcuts, mostly for compatibility with the old syntax
# .PHONY: all-keyboards
# all-keyboards: all\:all\:all
# .PHONY: all-keyboards-defaults
# all-keyboards-defaults: all\:default
# .PHONY: test
# test: test-all
# .PHONY: test-clean
# test-clean: test-all-clean
lib/%:
git submodule sync $?
git submodule update --init $?
@@ -557,13 +632,12 @@ else
endif
ifndef SKIP_VERSION
BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
else
BUILD_DATE := 2020-01-01-00:00:00
endif
$(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define CHIBIOS_VERSION "$(CHIBIOS_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define CHIBIOS_CONTRIB_VERSION "$(CHIBIOS_CONTRIB_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
else
BUILD_DATE := NA
endif
include $(ROOT_DIR)/testlist.mk

2
Vagrantfile vendored
View File

@@ -89,7 +89,7 @@ Vagrant.configure(2) do |config|
Examples:
make planck/rev4:default:dfu
make planck/rev4:default
make planck:default
EOT
end

View File

@@ -1 +0,0 @@
theme: jekyll-theme-cayman

View File

@@ -1,5 +0,0 @@
# QMK Keyboard Metadata
This directory contains machine parsable data about keyboards supported by QMK. The latest version is always available online at <https://keyboards.qmk.fm>.
Do not edit anything here by hand. It is generated with the `qmk generate-api` command.

1
autocomplete.sh Normal file

File diff suppressed because one or more lines are too long

81
bin/qmk
View File

@@ -2,61 +2,52 @@
"""CLI wrapper for running QMK commands.
"""
import os
import subprocess
import sys
from importlib.util import find_spec
from pathlib import Path
from time import strftime
# Add the QMK python libs to our path
script_dir = Path(os.path.realpath(__file__)).parent
qmk_dir = script_dir.parent
python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve()
sys.path.append(str(python_lib_dir))
script_dir = os.path.dirname(os.path.realpath(__file__))
qmk_dir = os.path.abspath(os.path.join(script_dir, '..'))
python_lib_dir = os.path.abspath(os.path.join(qmk_dir, 'lib', 'python'))
sys.path.append(python_lib_dir)
def _check_modules(requirements):
""" Check if the modules in the given requirements.txt are available.
"""
with Path(qmk_dir / requirements).open() as fd:
for line in fd.readlines():
line = line.strip().replace('<', '=').replace('>', '=')
if len(line) == 0 or line[0] == '#' or line.startswith('-r'):
continue
if '#' in line:
line = line.split('#')[0]
module = dict()
module['name'] = module['import'] = line.split('=')[0] if '=' in line else line
# Not every module is importable by its own name.
if module['name'] == "pep8-naming":
module['import'] = "pep8ext_naming"
if not find_spec(module['import']):
print('Could not find module %s!' % module['name'])
print('Please run `python3 -m pip install -r %s` to install required python dependencies.' % (qmk_dir / requirements,))
if developer:
print('You can also turn off developer mode: qmk config user.developer=None')
print()
exit(255)
developer = False
# Make sure our modules have been setup
_check_modules('requirements.txt')
with open(os.path.join(qmk_dir, 'requirements.txt'), 'r') as fd:
for line in fd.readlines():
line = line.strip().replace('<', '=').replace('>', '=')
if line[0] == '#':
continue
if '#' in line:
line = line.split('#')[0]
module = line.split('=')[0] if '=' in line else line
if module in ['pep8-naming']:
# Not every module is importable by its own name.
continue
if not find_spec(module):
print('Could not find module %s!' % module)
print('Please run `pip3 install -r requirements.txt` to install the python dependencies.')
exit(255)
# Figure out our version
# TODO(skullydazed/anyone): Find a method that doesn't involve git. This is slow in docker and on windows.
command = ['git', 'describe', '--abbrev=6', '--dirty', '--always', '--tags']
result = subprocess.run(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode == 0:
os.environ['QMK_VERSION'] = result.stdout.strip()
else:
os.environ['QMK_VERSION'] = 'nogit-' + strftime('%Y-%m-%d-%H:%M:%S') + '-dirty'
# Setup the CLI
import milc # noqa
# For developers additional modules are needed
if milc.cli.config.user.developer:
# Do not run the check for 'config',
# so users can turn off developer mode
if len(sys.argv) == 1 or (len(sys.argv) > 1 and 'config' != sys.argv[1]):
developer = True
_check_modules('requirements-dev.txt')
milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}'

View File

@@ -27,8 +27,6 @@
# qmk-dfu QMK DFU (LUFA + blinkenlight)
# bootloadHID HIDBootFlash compatible (ATmega32A)
# USBasp USBaspLoader (ATmega328P)
# kiibohd Input:Club Kiibohd bootloader (only used on their boards)
# stm32duino STM32Duino (STM32F103x8)
#
# BOOTLOADER_SIZE can still be defined manually, but it's recommended
# you add any possible configuration to this list
@@ -36,30 +34,30 @@
ifeq ($(strip $(BOOTLOADER)), atmel-dfu)
OPT_DEFS += -DBOOTLOADER_ATMEL_DFU
OPT_DEFS += -DBOOTLOADER_DFU
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
BOOTLOADER_SIZE = 4096
endif
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
ifeq ($(strip $(MCU)), at90usb1286)
BOOTLOADER_SIZE = 8192
endif
endif
ifeq ($(strip $(BOOTLOADER)), lufa-dfu)
OPT_DEFS += -DBOOTLOADER_LUFA_DFU
OPT_DEFS += -DBOOTLOADER_DFU
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
BOOTLOADER_SIZE = 4096
endif
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
ifeq ($(strip $(MCU)), at90usb1286)
BOOTLOADER_SIZE = 8192
endif
endif
ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
OPT_DEFS += -DBOOTLOADER_QMK_DFU
OPT_DEFS += -DBOOTLOADER_DFU
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
BOOTLOADER_SIZE = 4096
endif
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
ifeq ($(strip $(MCU)), at90usb1286)
BOOTLOADER_SIZE = 8192
endif
endif
@@ -91,30 +89,7 @@ ifeq ($(strip $(BOOTLOADER)), lufa-ms)
BOOTLOADER_SIZE = 6144
FIRMWARE_FORMAT = bin
endif
ifdef BOOTLOADER_SIZE
OPT_DEFS += -DBOOTLOADER_SIZE=$(strip $(BOOTLOADER_SIZE))
endif
ifeq ($(strip $(BOOTLOADER)), kiibohd)
OPT_DEFS += -DBOOTLOADER_KIIBOHD
ifeq ($(strip $(MCU_ORIG)), MK20DX128)
MCU_LDSCRIPT = MK20DX128BLDR4
endif
ifeq ($(strip $(MCU_ORIG)), MK20DX256)
MCU_LDSCRIPT = MK20DX256BLDR8
endif
DFU_ARGS = -d 1C11:B007
DFU_SUFFIX_ARGS = -v 1C11 -p B007
endif
ifeq ($(strip $(BOOTLOADER)), stm32duino)
OPT_DEFS += -DBOOTLOADER_STM32DUINO
MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
BOARD = STM32_F103_STM32DUINO
# STM32F103 does NOT have an USB bootloader in ROM (only serial), so setting anything here does not make much sense
STM32_BOOTLOADER_ADDRESS = 0x80000000
DFU_ARGS = -d 1EAF:0003 -a2 -R
DFU_SUFFIX_ARGS = -v 1EAF -p 0003
endif

View File

@@ -30,4 +30,4 @@ $(TEST)_SRC += $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
$(TEST)_DEFS=$(TMK_COMMON_DEFS) $(OPT_DEFS)
$(TEST)_CONFIG=$(TEST_PATH)/config.h
VPATH+=$(TOP_DIR)/tests/test_common
VPATH+=$(TOP_DIR)/tests/test_common

View File

@@ -21,11 +21,6 @@ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
endif
# Load the keymap-level rules.mk if exists
ifneq ("$(wildcard $(KEYMAP_PATH))", "")
-include $(KEYMAP_PATH)/rules.mk
endif
# Generate the keymap.c
$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
bin/qmk json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)
bin/qmk json-keymap --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)

View File

@@ -16,6 +16,7 @@ include common.mk
KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD))
TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP)
KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
STM32_PATH := quantum/stm32
# Force expansion
TARGET := $(TARGET)
@@ -90,16 +91,13 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_1)/rules.mk)","")
include $(KEYBOARD_PATH_1)/rules.mk
endif
MAIN_KEYMAP_PATH_1 := $(KEYBOARD_PATH_1)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_2 := $(KEYBOARD_PATH_2)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_3 := $(KEYBOARD_PATH_3)/keymaps/$(KEYMAP)
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 bin/qmk generate-rules-mk --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk)
include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c
include build_json.mk
@@ -139,7 +137,9 @@ ifeq ($(strip $(CTPC)), yes)
endif
ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes)
include platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk
TARGET := $(TARGET)_proton_c
include $(STM32_PATH)/proton_c.mk
OPT_DEFS += -DCONVERT_TO_PROTON_C
endif
ifneq ($(FORCE_LAYOUT),)
@@ -148,6 +148,12 @@ endif
include quantum/mcu_selection.mk
ifdef MCU_FAMILY
OPT_DEFS += -DQMK_STM32
KEYBOARD_PATHS += $(STM32_PATH)
endif
# Find all the C source files to be compiled in subfolders.
KEYBOARD_SRC :=
@@ -225,19 +231,44 @@ endif
# We can assume a ChibiOS target When MCU_FAMILY is defined since it's
# not used for LUFA
ifdef MCU_FAMILY
PLATFORM=CHIBIOS
PLATFORM_KEY=chibios
FIRMWARE_FORMAT?=bin
PLATFORM=CHIBIOS
else ifdef ARM_ATSAM
PLATFORM=ARM_ATSAM
PLATFORM_KEY=arm_atsam
FIRMWARE_FORMAT=bin
else
PLATFORM=AVR
PLATFORM_KEY=avr
FIRMWARE_FORMAT?=hex
endif
ifeq ($(PLATFORM),CHIBIOS)
include $(TMK_PATH)/chibios.mk
OPT_OS = chibios
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_5)/boards/$(BOARD)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_4)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_4)/boards/$(BOARD)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_3)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_3)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_3)/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_3)/boards/$(BOARD)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_2)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_2)/boards/$(BOARD)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_1)/bootloader_defs.h
else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_1)/boards/$(BOARD)/bootloader_defs.h
else ifneq ("$(wildcard $(TOP_DIR)/drivers/boards/$(BOARD)/bootloader_defs.h)","")
OPT_DEFS += -include $(TOP_DIR)/drivers/boards/$(BOARD)/bootloader_defs.h
endif
endif
# Find all of the config.h files and add them to our CONFIG_H define.
CONFIG_H :=
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","")
@@ -273,6 +304,11 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","")
POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h
endif
# Save the defines and includes here, so we don't include any keymap specific ones
PROJECT_DEFS := $(OPT_DEFS)
PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS)
PROJECT_CONFIG := $(CONFIG_H)
# Userspace setup and definitions
ifeq ("$(USER_NAME)","")
USER_NAME := $(KEYMAP)
@@ -293,32 +329,6 @@ ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
CONFIG_H += $(KEYMAP_PATH)/config.h
endif
# Pull in stuff from info.json
INFO_JSON_FILES :=
ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_1)/info.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_2)/info.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_3)/info.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_4)/info.json
endif
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_OUTPUT)/src/layouts.h
$(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
bin/qmk generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h
$(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES)
bin/qmk generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h
# project specific files
SRC += $(KEYBOARD_SRC) \
$(KEYMAP_C) \
@@ -344,24 +354,23 @@ SRC += $(TMK_COMMON_SRC)
OPT_DEFS += $(TMK_COMMON_DEFS)
EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
SKIP_COMPILE := no
ifneq ($(REQUIRE_PLATFORM_KEY),)
ifneq ($(REQUIRE_PLATFORM_KEY),$(PLATFORM_KEY))
SKIP_COMPILE := yes
endif
endif
include $(TMK_PATH)/$(PLATFORM_KEY).mk
ifneq ($(strip $(PROTOCOL)),)
include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk
ifeq ($(PLATFORM),AVR)
ifeq ($(strip $(PROTOCOL)), VUSB)
include $(TMK_PATH)/protocol/vusb.mk
else
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
include $(TMK_PATH)/protocol/lufa.mk
endif
include $(TMK_PATH)/avr.mk
endif
# TODO: remove this bodge?
PROJECT_DEFS := $(OPT_DEFS)
PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS)
PROJECT_CONFIG := $(CONFIG_H)
ifeq ($(PLATFORM),ARM_ATSAM)
include $(TMK_PATH)/arm_atsam.mk
include $(TMK_PATH)/protocol/arm_atsam.mk
endif
ifeq ($(PLATFORM),CHIBIOS)
include $(TMK_PATH)/protocol/chibios.mk
endif
ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
VISUALIZER_DIR = $(QUANTUM_DIR)/visualizer
@@ -386,16 +395,9 @@ $(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC) $(GFXINC)
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
# Default target.
ifeq ($(SKIP_COMPILE),no)
all: build check-size
else
all:
echo "skipped" >&2
endif
build: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/layouts.h elf cpfirmware
build: elf cpfirmware
check-size: build
check-md5: build
objs-size: build
include show_options.mk

View File

@@ -3,14 +3,8 @@ LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/))))
define SEARCH_LAYOUTS_REPO
LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP)
LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json
LAYOUT_KEYMAP_C := $$(LAYOUT_KEYMAP_PATH)/keymap.c
ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_JSON))","")
-include $$(LAYOUT_KEYMAP_PATH)/rules.mk
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $$(LAYOUT_KEYMAP_JSON)
KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH)
else ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","")
ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","")
-include $$(LAYOUT_KEYMAP_PATH)/rules.mk
KEYMAP_C := $$(LAYOUT_KEYMAP_C)
KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH)
@@ -30,7 +24,4 @@ ifneq ($(FORCE_LAYOUT),)
endif
endif
$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS)))
# Use rule from build_json.mk, but update prerequisite in case KEYMAP_JSON was updated
$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS)))

View File

@@ -17,7 +17,7 @@ OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
GTEST_INC := \
$(LIB_PATH)/googletest/googletest/include\
$(LIB_PATH)/googletest/googlemock/include\
GTEST_INTERNAL_INC :=\
$(LIB_PATH)/googletest/googletest\
$(LIB_PATH)/googletest/googlemock
@@ -27,7 +27,7 @@ $(GTEST_OUTPUT)_SRC :=\
googletest/src/gtest_main.cc\
googlemock/src/gmock-all.cc
$(GTEST_OUTPUT)_DEFS :=
$(GTEST_OUTPUT)_DEFS :=
$(GTEST_OUTPUT)_INC := $(GTEST_INC) $(GTEST_INTERNAL_INC)
LDFLAGS += -lstdc++ -lpthread -shared-libgcc
@@ -41,7 +41,6 @@ all: elf
VPATH += $(COMMON_VPATH)
PLATFORM:=TEST
PLATFORM_KEY:=test
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include tests/$(TEST)/rules.mk
@@ -49,7 +48,6 @@ endif
include common_features.mk
include $(TMK_PATH)/common.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk
include $(QUANTUM_PATH)/serial_link/tests/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include build_full_test.mk
@@ -66,3 +64,4 @@ include $(TMK_PATH)/rules.mk
$(shell mkdir -p $(BUILD_DIR)/test 2>/dev/null)
$(shell mkdir -p $(TEST_OBJ) 2>/dev/null)

View File

@@ -21,5 +21,4 @@ COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras
COMMON_VPATH += $(QUANTUM_PATH)/audio
COMMON_VPATH += $(QUANTUM_PATH)/process_keycode
COMMON_VPATH += $(QUANTUM_PATH)/api
COMMON_VPATH += $(QUANTUM_PATH)/sequencer
COMMON_VPATH += $(DRIVER_PATH)

View File

@@ -13,55 +13,52 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
SERIAL_DIR := $(QUANTUM_DIR)/serial_link
SERIAL_PATH := $(QUANTUM_PATH)/serial_link
QUANTUM_SRC += \
$(QUANTUM_DIR)/quantum.c \
$(QUANTUM_DIR)/led.c \
$(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/keycode_config.c
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
CONSOLE_ENABLE = yes
endif
SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
SERIAL_DEFS += -DSERIAL_LINK_ENABLE
COMMON_VPATH += $(SERIAL_PATH)
ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
OPT_DEFS += -DAPI_SYSEX_ENABLE
OPT_DEFS += -DAPI_ENABLE
MIDI_ENABLE=yes
SRC += $(QUANTUM_DIR)/api/api_sysex.c
OPT_DEFS += -DAPI_ENABLE
SRC += $(QUANTUM_DIR)/api.c
MIDI_ENABLE=yes
endif
MUSIC_ENABLE := 0
ifeq ($(strip $(AUDIO_ENABLE)), yes)
OPT_DEFS += -DAUDIO_ENABLE
MUSIC_ENABLE = yes
MUSIC_ENABLE := 1
SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c
SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c
SRC += $(QUANTUM_DIR)/audio/audio_$(PLATFORM_KEY).c
ifeq ($(PLATFORM),AVR)
SRC += $(QUANTUM_DIR)/audio/audio.c
else
SRC += $(QUANTUM_DIR)/audio/audio_arm.c
endif
SRC += $(QUANTUM_DIR)/audio/voices.c
SRC += $(QUANTUM_DIR)/audio/luts.c
endif
ifeq ($(strip $(SEQUENCER_ENABLE)), yes)
OPT_DEFS += -DSEQUENCER_ENABLE
MUSIC_ENABLE = yes
SRC += $(QUANTUM_DIR)/sequencer/sequencer.c
SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c
endif
ifeq ($(strip $(MIDI_ENABLE)), yes)
OPT_DEFS += -DMIDI_ENABLE
MUSIC_ENABLE = yes
MUSIC_ENABLE := 1
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif
MUSIC_ENABLE ?= no
ifeq ($(MUSIC_ENABLE), yes)
ifeq ($(MUSIC_ENABLE), 1)
SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
endif
ifeq ($(strip $(COMBO_ENABLE)), yes)
OPT_DEFS += -DCOMBO_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
endif
ifeq ($(strip $(STENO_ENABLE)), yes)
OPT_DEFS += -DSTENO_ENABLE
VIRTSER_ENABLE ?= yes
@@ -83,7 +80,29 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/pointing_device.c
endif
VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c
endif
ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
OPT_DEFS += -DUNICODEMAP_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c
endif
ifeq ($(strip $(UNICODE_ENABLE)), yes)
OPT_DEFS += -DUNICODE_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c
endif
ifeq ($(strip $(UNICODE_COMMON)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c
endif
VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c
EEPROM_DRIVER ?= vendor
ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),)
$(error EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver)
@@ -98,11 +117,6 @@ else
COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += i2c_master.c
SRC += eeprom_driver.c eeprom_i2c.c
else ifeq ($(strip $(EEPROM_DRIVER)), spi)
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI
COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += spi_master.c
SRC += eeprom_driver.c eeprom_spi.c
else ifeq ($(strip $(EEPROM_DRIVER)), transient)
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
COMMON_VPATH += $(DRIVER_PATH)/eeprom
@@ -127,21 +141,6 @@ else
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
OPT_DEFS += -DEEPROM_EMU_STM32F072xB
OPT_DEFS += -DSTM32_EEPROM_ENABLE
else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F042x6)
# Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced.
# This ensures that the EEPROM page buffer fits into RAM
USE_PROCESS_STACKSIZE = 0x600
USE_EXCEPTIONS_STACKSIZE = 0x300
SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
OPT_DEFS += -DEEPROM_EMU_STM32F042x6
OPT_DEFS += -DSTM32_EEPROM_ENABLE
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
OPT_DEFS += -DEEPROM_DRIVER
COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
else
# This will effectively work the same as "transient" if not supported by the chip
SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
@@ -154,48 +153,27 @@ else
endif
endif
RGBLIGHT_ENABLE ?= no
VALID_RGBLIGHT_TYPES := WS2812 APA102 custom
ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
RGBLIGHT_DRIVER ?= custom
endif
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
RGBLIGHT_DRIVER ?= WS2812
ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),)
$(error RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h
OPT_DEFS += -DRGBLIGHT_ENABLE
SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgblight.c
CIE1931_CURVE := yes
LED_BREATHING_TABLE := yes
RGB_KEYCODES_ENABLE := yes
ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
else
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h
OPT_DEFS += -DRGBLIGHT_ENABLE
SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgblight.c
CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes
endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812)
WS2812_DRIVER_REQUIRED := yes
endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102)
APA102_DRIVER_REQUIRED := yes
endif
ifeq ($(strip $(RGBLIGHT_DRIVER)), custom)
OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
endif
endif
VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom
LED_MATRIX_ENABLE ?= no
VALID_LED_MATRIX_TYPES := IS31FL3731 custom
# TODO: IS31FL3733 IS31FL3737 IS31FL3741
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
$(error LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type)
ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
ifeq ($(filter $(LED_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
$(error LED_MATRIX_ENABLE="$(LED_MATRIX_ENABLE)" is not a valid matrix type)
else
BACKLIGHT_ENABLE = yes
BACKLIGHT_DRIVER = custom
@@ -203,108 +181,107 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/led_matrix.c
SRC += $(QUANTUM_DIR)/led_matrix_drivers.c
endif
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3731-simple.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
OPT_DEFS += -DIS31FL3731
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3731-simple.c
QUANTUM_LIB_SRC += i2c_master.c
endif
RGB_MATRIX_ENABLE ?= no
VALID_RGB_MATRIX_TYPES := IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
$(error "$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
endif
OPT_DEFS += -DRGB_MATRIX_ENABLE
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
OPT_DEFS += -DLIB8_ATTINY
ifneq ($(strip $(RGB_MATRIX_ENABLE)), no)
ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
$(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type)
endif
OPT_DEFS += -DRGB_MATRIX_ENABLE
SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgb_matrix.c
SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c
CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3731.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
RGB_MATRIX_ENABLE := IS31FL3731
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733)
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3733.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3731.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)/issi
SRC += is31fl3737.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3733)
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3733.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741)
OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3741.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3737)
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi
SRC += is31fl3737.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812)
OPT_DEFS += -DWS2812
WS2812_DRIVER_REQUIRED := yes
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), WS2812)
OPT_DEFS += -DWS2812
WS2812_DRIVER_REQUIRED := yes
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102)
OPT_DEFS += -DAPA102
APA102_DRIVER_REQUIRED := yes
endif
ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
endif
ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
endif
ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes)
OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER
endif
ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes)
OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER
endif
ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_rgb.c
endif
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
OPT_DEFS += -DTAP_DANCE_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
endif
ifeq ($(strip $(KEY_LOCK_ENABLE)), yes)
OPT_DEFS += -DKEY_LOCK_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c
endif
ifeq ($(strip $(PRINTING_ENABLE)), yes)
OPT_DEFS += -DPRINTING_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c
SRC += $(TMK_DIR)/protocol/serial_uart.c
endif
ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
SERIAL_DEFS += -DSERIAL_LINK_ENABLE
COMMON_VPATH += $(SERIAL_PATH)
ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
OPT_DEFS += -DAUTO_SHIFT_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
endif
endif
ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
OPT_DEFS += $(SERIAL_DEFS)
VAPTH += $(SERIAL_PATH)
endif
VARIABLE_TRACE ?= no
ifneq ($(strip $(VARIABLE_TRACE)),no)
ifneq ($(strip $(VARIABLE_TRACE)),)
SRC += $(QUANTUM_DIR)/variable_trace.c
OPT_DEFS += -DNUM_TRACED_VARIABLES=$(strip $(VARIABLE_TRACE))
ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),)
OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE))
endif
ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),)
OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE))
endif
endif
ifeq ($(strip $(LCD_ENABLE)), yes)
@@ -316,28 +293,29 @@ ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
BACKLIGHT_DRIVER := custom
endif
VALID_BACKLIGHT_TYPES := pwm timer software custom
VALID_BACKLIGHT_TYPES := pwm software custom
BACKLIGHT_ENABLE ?= no
BACKLIGHT_DRIVER ?= pwm
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),)
$(error BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type)
endif
COMMON_VPATH += $(QUANTUM_DIR)/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 ifeq ($(strip $(BACKLIGHT_DRIVER)), software)
SRC += $(QUANTUM_DIR)/backlight/backlight_soft.c
else
SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c
ifeq ($(strip $(BACKLIGHT_DRIVER)), pwm)
SRC += $(QUANTUM_DIR)/backlight/backlight_$(PLATFORM_KEY).c
ifeq ($(PLATFORM),AVR)
SRC += $(QUANTUM_DIR)/backlight/backlight_avr.c
else
SRC += $(QUANTUM_DIR)/backlight/backlight_$(strip $(BACKLIGHT_DRIVER)).c
SRC += $(QUANTUM_DIR)/backlight/backlight_arm.c
endif
endif
endif
@@ -356,12 +334,6 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
SRC += ws2812.c
else
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
ifeq ($(strip $(PLATFORM)), CHIBIOS)
ifeq ($(strip $(WS2812_DRIVER)), pwm)
OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
endif
endif
endif
# add extra deps
@@ -370,11 +342,6 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
endif
endif
ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
COMMON_VPATH += $(DRIVER_PATH)/apa102
SRC += apa102.c
endif
ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
CIE1931_CURVE := yes
endif
@@ -384,6 +351,11 @@ ifeq ($(strip $(CIE1931_CURVE)), yes)
LED_TABLES := yes
endif
ifeq ($(strip $(LED_BREATHING_TABLE)), yes)
OPT_DEFS += -DUSE_LED_BREATHING_TABLE
LED_TABLES := yes
endif
ifeq ($(strip $(LED_TABLES)), yes)
SRC += $(QUANTUM_DIR)/led_tables.c
endif
@@ -398,16 +370,34 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes)
include $(TMK_DIR)/protocol/usb_hid.mk
endif
ifeq ($(strip $(WPM_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/wpm.c
OPT_DEFS += -DWPM_ENABLE
endif
ifeq ($(strip $(ENCODER_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/encoder.c
OPT_DEFS += -DENCODER_ENABLE
endif
HAPTIC_ENABLE ?= no
ifneq ($(strip $(HAPTIC_ENABLE)),no)
COMMON_VPATH += $(DRIVER_PATH)/haptic
SRC += haptic.c
OPT_DEFS += -DHAPTIC_ENABLE
endif
ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
SRC += DRV2605L.c
QUANTUM_LIB_SRC += i2c_master.c
OPT_DEFS += -DDRV2605L
endif
ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), )
SRC += solenoid.c
OPT_DEFS += -DSOLENOID_ENABLE
endif
ifeq ($(strip $(HD44780_ENABLE)), yes)
SRC += drivers/avr/hd44780.c
OPT_DEFS += -DHD44780_ENABLE
endif
ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
OPT_DEFS += -DVELOCIKEY_ENABLE
SRC += $(QUANTUM_DIR)/velocikey.c
@@ -426,11 +416,26 @@ ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/dynamic_keymap.c
endif
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
OPT_DEFS += -DDIP_SWITCH_ENABLE
SRC += $(QUANTUM_DIR)/dip_switch.c
ifeq ($(strip $(LEADER_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c
OPT_DEFS += -DLEADER_ENABLE
endif
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/dip_switch.c
OPT_DEFS += -DDIP_SWITCH_ENABLE
endif
include $(DRIVER_PATH)/qwiic/qwiic.mk
QUANTUM_SRC:= \
$(QUANTUM_DIR)/quantum.c \
$(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/keycode_config.c
VALID_CUSTOM_MATRIX_TYPES:= yes lite no
CUSTOM_MATRIX ?= no
@@ -454,20 +459,9 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes)
endif
endif
# Support for translating old names to new names:
ifeq ($(strip $(DEBOUNCE_TYPE)),sym_g)
DEBOUNCE_TYPE:=sym_defer_g
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pk)
DEBOUNCE_TYPE:=sym_eager_pk
else ifeq ($(strip $(DEBOUNCE_TYPE)),sym_pk)
DEBOUNCE_TYPE:=sym_defer_pk
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pr)
DEBOUNCE_TYPE:=sym_eager_pr
endif
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually.
DEBOUNCE_TYPE?= sym_defer_g
DEBOUNCE_TYPE?= sym_g
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
endif
@@ -485,14 +479,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
# Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called.
# Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
ifeq ($(PLATFORM),AVR)
ifneq ($(NO_I2C),yes)
QUANTUM_LIB_SRC += i2c_master.c \
i2c_slave.c
endif
QUANTUM_LIB_SRC += i2c_master.c \
i2c_slave.c
endif
SERIAL_DRIVER ?= bitbang
OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
QUANTUM_LIB_SRC += serial.c
else
@@ -502,29 +493,6 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
COMMON_VPATH += $(QUANTUM_PATH)/split_common
endif
HAPTIC_ENABLE ?= no
ifneq ($(strip $(HAPTIC_ENABLE)),no)
COMMON_VPATH += $(DRIVER_PATH)/haptic
SRC += haptic.c
OPT_DEFS += -DHAPTIC_ENABLE
endif
ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
SRC += DRV2605L.c
QUANTUM_LIB_SRC += i2c_master.c
OPT_DEFS += -DDRV2605L
endif
ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), )
SRC += solenoid.c
OPT_DEFS += -DSOLENOID_ENABLE
endif
ifeq ($(strip $(HD44780_ENABLE)), yes)
SRC += drivers/avr/hd44780.c
OPT_DEFS += -DHD44780_ENABLE
endif
ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
OPT_DEFS += -DOLED_DRIVER_ENABLE
COMMON_VPATH += $(DRIVER_PATH)/oled
@@ -532,34 +500,10 @@ ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
SRC += oled_driver.c
endif
include $(DRIVER_PATH)/qwiic/qwiic.mk
ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c
endif
ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
OPT_DEFS += -DUNICODEMAP_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c
endif
ifeq ($(strip $(UNICODE_ENABLE)), yes)
OPT_DEFS += -DUNICODE_ENABLE
UNICODE_COMMON := yes
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c
endif
ifeq ($(strip $(UNICODE_COMMON)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c
endif
SPACE_CADET_ENABLE ?= yes
ifeq ($(strip $(SPACE_CADET_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
OPT_DEFS += -DSPACE_CADET_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
OPT_DEFS += -DSPACE_CADET_ENABLE
endif
MAGIC_ENABLE ?= yes
@@ -578,47 +522,3 @@ ifeq ($(strip $(DYNAMIC_MACRO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_dynamic_macro.c
OPT_DEFS += -DDYNAMIC_MACRO_ENABLE
endif
ifeq ($(strip $(COMBO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
OPT_DEFS += -DCOMBO_ENABLE
endif
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
OPT_DEFS += -DTAP_DANCE_ENABLE
endif
ifeq ($(strip $(KEY_LOCK_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c
OPT_DEFS += -DKEY_LOCK_ENABLE
endif
ifeq ($(strip $(LEADER_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c
OPT_DEFS += -DLEADER_ENABLE
endif
ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
OPT_DEFS += -DAUTO_SHIFT_ENABLE
ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
endif
endif
JOYSTICK_ENABLE ?= no
ifneq ($(strip $(JOYSTICK_ENABLE)), no)
OPT_DEFS += -DJOYSTICK_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c
SRC += $(QUANTUM_DIR)/joystick.c
endif
ifeq ($(strip $(JOYSTICK_ENABLE)), analog)
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE
SRC += analog.c
endif
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
endif

View File

@@ -50,3 +50,4 @@ This document marks the inaugural Breaking Change merge. A list of changes follo
* `KC_DELT` was a redundant, undocumented alias for `KC_DELETE`
* It has been removed and all its uses replaced with the more common `KC_DEL` alias
* Around 90 keymaps (mostly for ErgoDox boards) have been modified as a result

View File

@@ -1,239 +0,0 @@
# QMK Breaking Change - 2020 May 30 Changelog
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
The list of changes follows.
## Core Changes
### Converting V-USB usbdrv to a submodule
[#8321](https://github.com/qmk/qmk_firmware/pull/8321) and [qmk_compiler#62](https://github.com/qmk/qmk_compiler/pull/62).
These PRs move the V-USB driver code out of the qmk_firmware repository and into a submodule pointed at https://github.com/obdev/v-usb. This will make it easier to update the codebase if needed, while applying any potential QMK-specific modifications by forking it to the QMK GitHub organization.
### Unify Tap Hold functions and documentation
[#8348](https://github.com/qmk/qmk_firmware/pull/8348)
Updates all of the per key tap-hold functions to pass the `keyrecord_t` structure, and include documentation changes.
Any remaining versions or code outside of the main repo will need to be converted:
| Old function | New Function |
|------------------------------------------------------|---------------------------------------------------------------------------|
|`uint16_t get_tapping_term(uint16_t keycode)` |`uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record)` |
|`bool get_ignore_mod_tap_interrupt(uint16_t keycode)` |`bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record)` |
### Python Required In The Build Process
[#9000](https://github.com/qmk/qmk_firmware/pull/9000)
This is the last release of QMK that will work without having Python 3.6 (or later) installed. If your environment is not fully setup you will get a warning instructing you to set it up.
After the next breaking change you will not be able to build if `bin/qmk hello` does not work.
### Upgrade from tinyprintf to mpaland/printf
[#8269](https://github.com/qmk/qmk_firmware/pull/8269)
- Provides debug functionality on ChibiOS/ARM that is more compliant than previous integrations.
- Less maintenence, fewer QMK customisations, and allows QMK to sidestep previous compile and runtime issues.
- A `make git-submodule` may be required after pulling the latest QMK Firmware code to update to the new dependency.
### Fixed RGB_DISABLE_AFTER_TIMEOUT to be seconds based & small internals cleanup
[#6480](https://github.com/qmk/qmk_firmware/pull/6480)
- Changes `RGB_DISABLE_AFTER_TIMEOUT` to be based on milliseconds instead of ticks.
- Includes a code cleanup, resulting in a savings of 100 bytes, depending on features used.
- Fixed issues with timeouts / suspending at the wrong time not turning off all LEDs in some cases.
The `RGB_DISABLE_AFTER_TIMEOUT` definition is now deprecated, and has been superseded by `RGB_DISABLE_TIMEOUT`. To use the new definition, rename `RGB_DISABLE_AFTER_TIMEOUT` to `RGB_DISABLE_TIMEOUT` in your `config.h` file, and multiply the value set by 1200.
Before: `#define RGB_DISABLE_AFTER_TIMEOUT 100`
After: `#define RGB_DISABLE_TIMEOUT 120000`
### Switch to qmk forks for everything
[#9019](https://github.com/qmk/qmk_firmware/pull/9019)
Fork all QMK submodules to protect against upstream repositories disappearing.
### code cleanup regarding deprecated macro PLAY_NOTE_ARRAY by replacing it with PLAY_SONG
[#8484](https://github.com/qmk/qmk_firmware/pull/8484)
Removes the deprecated `PLAY_NOTE_ARRAY` macro. References to it are replaced with `PLAY_SONG`, which references the same function.
### fixing wrong configuration of AUDIO feature
[#8903](https://github.com/qmk/qmk_firmware/pull/8903) and [#8974](https://github.com/qmk/qmk_firmware/pull/8974)
`audio_avr.c` does not default to any pin; there has to be a #define XX_AUDIO in config.h at some level for Audio to actually work. Otherwise, the Audio code ends up cluttering the firmware, possibly breaking builds because the maximum allowed firmware size is exceeded.
These changes fix this by disabling Audio on keyboards that have the feature misconfigured, and therefore non-functional.
Also, add a compile-time error to alert the user to a missing pin-configuration (on AVR boards) when `AUDIO_ENABLE = yes` is set.
## Keyboard Refactors
### Migrating Lily58 to use split_common
[#6260](https://github.com/qmk/qmk_firmware/pull/6260)
Modifies the default firmware for Lily58 to use the `split_common` library, instead of including and depending on its own set of libraries for the following functionality:
- SSD1306 display
- i2c for OLED
- Serial Communication
This allows current lily58 firmware to advance with updates to the `split_common` library, which is shared with many other split keyboards.
#### To migrate existing Lily58 firmware:
[Changes to `config.h`](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-445ac369c8717dcd6fc6fc3630836fc1):
- Remove `#define SSD1306OLED` from config.h
[Changes to `keymap.c`](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7):
- Find/Replace each instance of `#ifdef SSD1306OLED` with `#ifdef OLED_DRIVER_ENABLE`
- The following changes are for compatibility with the OLED driver. If you don't use the OLED driver you may safely delete [this section](https://github.com/qmk/qmk_firmware/blob/e6b9980bd45c186f7360df68c24b6e05a80c10dc/keyboards/lily58/keymaps/default/keymap.c#L144-L190)
- Alternatively, if you did not change the OLED code from that in `default`, you may find it easier to simply copy the [relevant section](https://github.com/qmk/qmk_firmware/blob/4ac310668501ae6786c711ecc8f01f62ddaa1c0b/keyboards/lily58/keymaps/default/keymap.c#L138-L172). Otherwise, the changes you need to make are as follows (sample change [here](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7R138-R173))
- [Remove](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7L138-L141) the block
```c
#ifdef SSD1306OLED
iota_gfx_init(!has_usb()); // turns on the display
#endif
```
- Within the block bounded by `#ifdef OLED_DRIVER_ENABLE` and `#endif // OLED_DRIVER_ENABLE`, add the following block to ensure that your two OLEDs are rotated correctly across the left and right sides:
```c
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
if (!is_keyboard_master())
return OLED_ROTATION_180; // flips the display 180 degrees if offhand
return rotation;
}
```
- Remove the functions `matrix_scan_user`, `matrix_update` and `iota_gfx_task_user`
- Find/Replace `matrix_render_user(struct CharacterMatrix *matrix)` with `iota_gfx_task_user(void)`
- Find/Replace `is_master` with `is_keyboard_master()`
- For each instance of `matrix_write_ln(matrix, display_fn())`, rewrite it as `oled_write_ln(read_layer_state(), false);`
- For each instance of `matrix_write(matrix, read_logo());`, replace with `oled_write(read_logo(), false);`
### Refactor zinc to use split_common
[#7114](https://github.com/qmk/qmk_firmware/pull/7114) and [#9171](https://github.com/qmk/qmk_firmware/pull/9171)
* Refactor to use split_common and remove split codes under the zinc/revx/
* Add - backlight RGB LED and/or underglow RGB LED option
* Add - continuous RGB animations feature (between L and R halves)
* Fix - keymap files to adapt to changes
* all authors of keymaps confirmed this PR
* Update - documents and rules.mk
### Refactor of TKC1800 to use common OLED code
[#8472](https://github.com/qmk/qmk_firmware/pull/8472)
Modifies the default firmware for TKC1800 to use the in-built I2C and OLED drivers, instead of including and depending on its own set of libraries for the following functionality:
- SSD1306 display
- i2c for OLED
This allows current TKC1800 firmware to advance with updates to those drivers, which are shared with other keyboards.
#### To migrate existing TKC1800 firmware:
[Changes to `config.h`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-d10b26e676b4a55cbb00d71955116526):
- Remove `#define SSD1306OLED` from config.h
[Changes to `tkc1800.c`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-3b35bd30abe89c8110717c6972cd2cc5):
- Add the following to avoid debug errors on HID_listen if the screen is not present
```c
void keyboard_pre_init_kb(void) {
setPinInputHigh(D0);
setPinInputHigh(D1);
keyboard_pre_init_user();
}
```
[Changes to `keymap.c`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-05a2a344ce27e4d045fe68520ccd4771):
- Find/Replace each instance of `#ifdef SSD1306OLED` with `#ifdef OLED_DRIVER_ENABLE`
- The following changes are for compatibility with the OLED driver. If you don't use the OLED driver you may safely delete [this section](https://github.com/qmk/qmk_firmware/blob/e6b9980bd45c186f7360df68c24b6e05a80c10dc/keyboards/lily58/keymaps/default/keymap.c#L144-L190)
- [Remove](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7L91-L158) the block
```c
#ifdef SSD1306OLED
iota_gfx_init(!has_usb()); // turns on the display
#endif
```
- Within the block bounded by `#ifdef OLED_DRIVER_ENABLE` and `#endif // OLED_DRIVER_ENABLE`, add the following block to ensure that your two OLEDs are rotated correctly across the left and right sides:
```c
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
if (!is_keyboard_master())
return OLED_ROTATION_180; // flips the display 180 degrees if offhand
return rotation;
}
```
- Remove the function `iota_gfx_task_user`
### Split HHKB to ANSI and JP layouts and Add VIA support for each
[#8582](https://github.com/qmk/qmk_firmware/pull/8582)
- Splits the HHKB codebase into two separate folders `keyboards/hhkb/ansi` and `keyboards/hhkb/jp`.
- Adds VIA Configurator support for both versions.
#### Migrating existing HHKB keymaps
- Remove any checks for the `HHKB_JP` definition
- All checks for this definition have been removed, and each version uses the source that is appropriate to that version.
- Move the directory for your keymap into the appropriate `keymaps` directory
- `keyboards/hhkb/ansi/keymaps/` for ANSI HHKBs
- `keyboards/hhkb/jp/keymaps/` for HHKB JPs
- Compile with the new keyboard names
- This PR changes the compilation instructions for the HHKB Alternate Controller. To compile firmware for this controller moving forward, use:
- `make hhkb/ansi` for ANSI-layout HHKBs
- `make hhkb/jp` for HHKB JP keyboards
## Keyboard Moves
- [#8412](https://github.com/qmk/qmk_firmware/pull/8412 "Changing board names to prevent confusion") by blindassassin111
- [#8499](https://github.com/qmk/qmk_firmware/pull/8499 "Move the Keyboardio Model01 to a keyboardio/ subdir") by algernon
- [#8830](https://github.com/qmk/qmk_firmware/pull/8830 "Move spaceman keyboards") by Spaceman (formerly known as Rionlion100)
- [#8537](https://github.com/qmk/qmk_firmware/pull/8537 "Organizing my keyboards (plaid, tartan, ergoinu)") by hsgw
Keyboards by Keyboardio, Spaceman, and hsgw move to vendor folders, while PCBs designed by blindassassin111 are renamed.
Old Name | New Name
:----------------- | :-----------------
2_milk | spaceman/2_milk
at101_blackheart | at101_bh
ergoinu | dm9records/ergoinu
model01 | keyboardio/model01
omnikey_blackheart | omnikey_bh
pancake | spaceman/pancake
plaid | dm9records/plaid
tartan | dm9records/tartan
z150_blackheart | z150_bh
If you own one of these PCBs, please use the new names to compile your firmware moving forward.
## Keycode Migration PRs
[#8954](https://github.com/qmk/qmk_firmware/pull/8954 "Migrate `ACTION_LAYER_TOGGLE` to `TG()`"), [#8957](https://github.com/qmk/qmk_firmware/pull/8957 "Migrate `ACTION_MODS_ONESHOT` to `OSM()`"), [#8958](https://github.com/qmk/qmk_firmware/pull/8958 "Migrate `ACTION_DEFAULT_LAYER_SET` to `DF()`"), [#8959](https://github.com/qmk/qmk_firmware/pull/8959 "Migrate `ACTION_LAYER_MODS` to `LM()`"), [#8968](https://github.com/qmk/qmk_firmware/pull/8968 "Migrate `ACTION_MODS_TAP_KEY` to `MT()`"), [#8977](https://github.com/qmk/qmk_firmware/pull/8977 "Migrate miscellaneous `fn_actions` entries"), and [#8979](https://github.com/qmk/qmk_firmware/pull/8979 "Migrate `ACTION_MODS_KEY` to chained mod keycodes")
Authored by fauxpark, these pull requests remove references to deprecated TMK macros that have been superseded by native QMK keycodes.
Old `fn_actions` action | New QMK keycode
:---------------------- | :--------------
`ACTION_DEFAULT_LAYER_SET(layer)` | `DF(layer)`
`ACTION_LAYER_MODS(layer, mod)` | `LM(layer, mod)`
`ACTION_LAYER_ONESHOT(mod)` | `OSL(mod)`
`ACTION_LAYER_TOGGLE(layer)` | `TG(layer)`
`ACTION_MODS_ONESHOT(mod)` | `OSM(mod)`
`ACTION_MODS_TAP_KEY(mod, kc)` | `MT(mod, kc)`
`ACTION_MODS_KEY(mod, kc)`<br>e.g. `ACTION_MODS_KEY(MOD_LCTL, KC_0)` | `MOD(kc)`<br>e.g. `LCTL(KC_0)`

View File

@@ -1,148 +0,0 @@
# QMK Breaking Change - 2020 Aug 29 Changelog
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
## Changes Requiring User Action :id=changes-requiring-user-action
### Relocated Keyboards :id-relocated-keyboards
#### The Key Company project consolidation ([#9547](https://github.com/qmk/qmk_firmware/pull/9547))
#### relocating boards by flehrad to flehrad/ folder ([#9635](https://github.com/qmk/qmk_firmware/pull/9635))
Keyboards released by The Key Company and keyboards designed by flehrad have moved to vendor folders. If you own any of the keyboards listed below, please use the new names to compile your firmware moving forward.
Old Name | New Name
:--------------------- | :------------------
candybar/lefty | tkc/candybar/lefty
candybar/righty | tkc/candybar/righty
m0lly | tkc/m0lly
tkc1800 | tkc/tkc1800
bigswitch | flehrad/bigswitch
handwired/downbubble | flehrad/downbubble
handwired/numbrero | flehrad/numbrero
snagpad | flehrad/snagpad
handwired/tradestation | flehrad/tradestation
### Updated Keyboard Codebases :id=keyboard-updates
#### Keebio RGB wiring update ([#7754](https://github.com/qmk/qmk_firmware/pull/7754))
This pull request changes the configuration for Keebio split boards to use the same RGB strip wiring for each half, which provides the following improvements:
* Easier wiring due to one fewer wire needed (the wire between left DOut to extra data pin) and the fact that wiring is the same for both halves.
* RGB LEDs can be controlled by each half now instead of just master half.
* Extra data line is freed up to allow for I2C usage instead of serial.
If you have customized the value of `RGBLED_SPLIT` for your keymap, you will need to undefine it using `#undef RGBLED_SPLIT` before defining it to your customized value.
This change affects:
* BFO-9000
* Fourier
* Iris rev2
* Levinson, revs. 1 and 2
* Nyquist, revs. 1 and 2
* Quefrency rev1
* Viterbi, revs. 1 and 2
### Changes to Core Functionality :id=core-updates
* Bigger Combo index ([#9318](https://github.com/qmk/qmk_firmware/pull/9318))
Allows the Combo feature to support more than 256 combos.
Any fork that uses `process_combo_event` needs to update the function's first argument to `uint16_t`:
* Old function: `void process_combo_event(uint8_t combo_index, bool pressed)`
* New function: `void process_combo_event(uint16_t combo_index, bool pressed)`
## Core Changes :id=core-changes
### Fixes :id=core-fixes
* Mousekeys: scrolling acceleration is no longer coupled to mouse movement acceleration ([#9174](https://github.com/qmk/qmk_firmware/pull/9174))
* Keymap Extras: correctly assign Question Mark in Czech layout ([#9987](https://github.com/qmk/qmk_firmware/pull/9987))
### Additions and Enhancements :id=core-additions
* allow for WS2812 PWM to work on DMAMUX-capable devices ([#9471](https://github.com/qmk/qmk_firmware/pull/9471))
* Newer STM32 MCUs have a DMAMUX peripheral, which allows mapping of DMAs to different DMA streams, rather than hard-defining the target streams in silicon.
* Affects STM32L4+ devices, as well as the soon-to-be-supported-by-QMK STM32G4/H7 families.
* Tested on F303/Proton C (ChibiOS v19, non-DMAMUX), G474 (ChibiOS v20, with DMAMUX).
* dual-bank STM32 bootloader support ([#8778](https://github.com/qmk/qmk_firmware/pull/8778) and [#9738](https://github.com/qmk/qmk_firmware/pull/9738))
* Adds support for STM32 dual-bank flash bootloaders, by toggling a GPIO during early init in order to charge an RC circuit attached to `BOOT0`.
* The main rationale behind this is that dual-bank STM32 devices unconditionally execute user-mode code, regardless of whether or not the user-mode code jumps to the bootloader. If either flash bank is valid (and `BOOT0` is low), then the built-in bootloader will skip any sort of DFU.
* This PR allows for the initialisation sequencing to charge the RC circuit based on the example circuit posted on Discord, effectively pulling `BOOT0` high before issuing the system reset. As the RC circuit takes a while to discharge, the system reset executes the ROM bootloader which subsequently sees `BOOT0` high, and starts executing the DFU routines.
* Tested with STM32L082 (with current QMK+current ChibiOS), and STM32G474 (against ChibiOS 20.x).
* update Space Cadet and Tap Dance features to use Custom Tapping Term when appropriate ([#6259](https://github.com/qmk/qmk_firmware/pull/6259))
* For the Tap Dance feature, this completely removes the need for the `ACTION_TAP_DANCE_FN_ADVANCED_TIME` dance.
* HID Joystick Interface ([#4226](https://github.com/qmk/qmk_firmware/pull/4226) and [#9949](https://github.com/qmk/qmk_firmware/pull/9949 "Fix Joystick Compile Issues"))
* This implements a joystick feature, including a joystick_task function called from TMK, specific keycodes for joystick buttons and a USB HID interface.
* Tested on V-USB backend and Proton C; compiles but untested on LUFA.
* In order to test, you have to add `JOYSTICK_ENABLE = yes` to your `rules.mk` and
```c
#define JOYSTICK_BUTTON_COUNT 8
#define JOYSTICK_AXES_COUNT 2
```
in your config.h.
* Christmas RGB Underglow animation now fades between green and red ([#7648](https://github.com/qmk/qmk_firmware/pull/7648))
* `RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL` has been greatly decreased; please check your animation if you have customized this value.
* layer state now initializes on startup ([#8318](https://github.com/qmk/qmk_firmware/pull/8318))
* This should produce more consistent behavior between the two functions and layer masks.
* added support for HSV->RGB conversion without using CIE curve ([#9856](https://github.com/qmk/qmk_firmware/pull/9856))
* added NOEEPROM functions for RGB Matrix ([#9487](https://github.com/qmk/qmk_firmware/pull/9487))
* Added eeprom_helpers for toggle, mode, sethsv, speed, similar to rgblight versions.
* Added set_speed function.
* Added helper functions, similar to those in rgblight, in order to add NOEEPROM versions of toggle, step, hue, sat, val, and speed.
* Minor: spelling correction for EEPROM in a debug message.
* flashing firmware using `st-flash` utility from [STLink Tools](https://github.com/stlink-org/stlink) is now supported ([#9964](https://github.com/qmk/qmk_firmware/pull/9964))
* add ability to dump all makefile variables for the specified target ([#8256](https://github.com/qmk/qmk_firmware/pull/8256))
* Adds a new subtarget to builds, `dump_vars`, which allows for printing out all the variables that make knows about, after all substitutions occur.
* Example: `make handwired/onekey/proton_c:default:dump_vars`
* add ability to change the Auto Shift timeout in real time ([#8441](https://github.com/qmk/qmk_firmware/pull/8441))
* added a timer implementation for backlight on ChibiOS ([#8291](https://github.com/qmk/qmk_firmware/pull/8291))
* added a third endpoint to V-USB keyboards ([#9020](https://github.com/qmk/qmk_firmware/pull/9020))
* added a method to read the OLED display buffer from user space ([#8777](https://github.com/qmk/qmk_firmware/pull/8777))
* K-Type refactor ([#9864](https://github.com/qmk/qmk_firmware/pull/9864))
* The K-Type has been refactored to use QMK's native matrix scanning routine, and now has partial support for the RGB Matrix feature.
* Joysticks can now be used without defining analog pins ([#10169](https://github.com/qmk/qmk_firmware/pull/10169))
### Clean-ups and Optimizations :id=core-optimizations
* iWRAP protocol removed ([#9284](https://github.com/qmk/qmk_firmware/pull/9284))
* work begun for consolidation of ChibiOS platform files ([#8327](https://github.com/qmk/qmk_firmware/pull/8327) and [#9315](https://github.com/qmk/qmk_firmware/pull/9315))
* Start of the consolidation work to move the ChibiOS board definitions as well as the default set of configuration files for existing board definitions used by keyboards.
* Uses `/platforms/chibios` as previously discussed on discord.
* Consolidates the Proton C configs into the generic F303 definitions.
* Allows for defining a default set of `chconf.h`, `halconf.h`, and `mcuconf.h` files within the platform definition, which is able to be overridden by the keyboard directly, though include path ordering.
* Adds template `chconf.h`, `halconf.h`, `mcuconf.h`, and `board.h` that can be dropped into a keyboard directory, in order to override rather than replace the entire contents of the respective files.
* Removed Proton C QMK board definitions, falling back to ChibiOS board definitions with QMK overrides.
* Various tidy-ups for USB descriptor code ([#9005](https://github.com/qmk/qmk_firmware/pull/9005))
* Renamed `keyboard_led_stats` in lufa.c and ChibiOS usb_main.c to `keyboard_led_state`, as well as `vusb_keyboard_leds`, for consistency
* Formatted CDC and MIDI descriptors better
* Removed `ENDPOINT_CONFIG` macro, it seems pointless and removes the need for endpoint address defines in the middle of the endpoint numbering enum
* Fixed (possibly?) V-USB `GET_REPORT` request handling. Not sure about this one, but the existing code appears to always return an empty report - now `send_keyboard` sets this variable to the current report, matching what the LUFA code does.
* converted `CONSUMER2BLUEFRUIT()` and `CONSUMER2RN42()` macros to static inline functions ([#9055](https://github.com/qmk/qmk_firmware/pull/9055))
* Additional cleanups for V-USB code ([#9310](https://github.com/qmk/qmk_firmware/pull/9310))
* Removing the UART stuff entirely, now that we have Console support. Also fixing up various other things; switching some `debug()` calls to `dprintf()`, moved `raw_hid_report` out of the way so that we can implement the shared endpoint stuff.
* removed inclusion of `adafruit_ble.h` from `ssd1306.c` ([#9355](https://github.com/qmk/qmk_firmware/pull/9355))
* `outputselect.c` is no longer compiled if Bluetooth is disabled ([#9356](https://github.com/qmk/qmk_firmware/pull/9356))
* `analogRead()` deprecated in favor of `analogReadPin()` ([#9023](https://github.com/qmk/qmk_firmware/pull/9023))
* forcibly disable NKRO on V-USB controllers ([#9054](https://github.com/qmk/qmk_firmware/pull/9054))
* removed warning if running backlight on STM32F072 ([#10040](https://github.com/qmk/qmk_firmware/pull/10040))
* removed unused CORTEX_VTOR_INIT rules.mk option ([#10053](https://github.com/qmk/qmk_firmware/pull/10053))
* improved handling for enabling Link Time Optimization ([#9832](https://github.com/qmk/qmk_firmware/pull/9832))
* streamline rules for supporting Kiibohd bootloader ([#10129](https://github.com/qmk/qmk_firmware/pull/10129))
* Define `STM32_DMA_REQUIRED` when using DMA-based WS2812 driver on STM32 ([#10127](https://github.com/qmk/qmk_firmware/pull/10127))
* fix DMA stream ID calculation in ws2812_pwm ([#10008](https://github.com/qmk/qmk_firmware/pull/10008))
* remove support for Adafruit EZ Key Bluetooth controller ([#10103](https://github.com/qmk/qmk_firmware/pull/10103))
## QMK Infrastructure and Internals :id=qmk-internals
* Attempt to fix CI for non-master branches. ([#9308](https://github.com/qmk/qmk_firmware/pull/9308))
* Actually fetch the branch we're attempting to compare against.
* Run `qmk cformat` on `develop` branch ([#9501](https://github.com/qmk/qmk_firmware/pull/9501))
* minor refactor of Bluetooth API ([#9905](https://github.com/qmk/qmk_firmware/pull/9905))

View File

@@ -1,150 +0,0 @@
# QMK Breaking Change - 2020 Nov 28 Changelog
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
## Changes Requiring User Action :id=changes-requiring-user-action
### Relocated Keyboards :id-relocated-keyboards
#### Reduce Helix keyboard build variation ([#8669](https://github.com/qmk/qmk_firmware/pull/8669))
The build commands for the Helix keyboard are:
```
make <helix_build_name>:<keymap_name>
```
For `<helix_build_name>`, specify the one in the rightmost column of the table below, such as `helix`,` helix/pico`.
| before Oct 17 2019 | Oct 17 2019 | Mar 10 2020 | Nov 28 2020 |
| ---------------------|-------------------------|-------------------------| ------------------------|
| helix/rev1 | helix/rev1 | helix/rev1 | helix/rev1 |
| helix/pico | helix/pico | helix/pico | helix/pico |
| | helix/pico/back | helix/pico/back | helix/pico/back |
| | helix/pico/under | helix/pico/under | helix/pico/under |
| | | helix/pico/sc | -- |
| | | helix/pico/sc/back | helix/pico/sc |
| | | helix/pico/sc/under | -- |
| helix/rev2 (=helix) | helix/rev2 (=helix) | helix/rev2 (=helix) | -- |
| | helix/rev2/back | helix/rev2/back | -- |
| | helix/rev2/back/oled | helix/rev2/back/oled | ( --> helix/rev2/back) |
| | helix/rev2/oled | helix/rev2/oled | helix/rev2 (=helix) |
| | helix/rev2/oled/back | helix/rev2/oled/back | helix/rev2/back |
| | helix/rev2/oled/under | helix/rev2/oled/under | helix/rev2/under |
| | | helix/rev2/sc | -- |
| | | helix/rev2/sc/back | -- |
| | | helix/rev2/sc/oled | -- |
| | | helix/rev2/sc/oledback | helix/rev2/sc |
| | | helix/rev2/sc/oledunder | -- |
| | | helix/rev2/sc/under | -- |
| | helix/rev2/under | helix/rev2/under | -- |
| | helix/rev2/under/oled | helix/rev2/under/oled | ( --> helix/rev2/under) |
#### Update the Speedo firmware for v3.0 ([#10657](https://github.com/qmk/qmk_firmware/pull/10657))
The Speedo keyboard has moved to `cozykeys/speedo/v2` as the designer prepares to release the Speedo v3.0.
| Previous Name | New Name |
| :------------ | :------------------------- |
| speedo | cozykeys/speedo/v2 |
| -- | cozykeys/speedo/v3 **new** |
#### Maartenwut/Maarten name change to evyd13/Evy ([#10274](https://github.com/qmk/qmk_firmware/pull/10274))
Maartenwut has rebranded as @evyd13, and all released Maartenwut boards have moved.
| Previous Name | New Name |
| :--------------------- | :----------------- |
| maartenwut/atom47/rev2 | evyd13/atom47/rev2 |
| maartenwut/atom47/rev3 | evyd13/atom47/rev3 |
| maartenwut/eon40 | evyd13/eon40 |
| maartenwut/eon65 | evyd13/eon65 |
| maartenwut/eon75 | evyd13/eon75 |
| maartenwut/eon87 | evyd13/eon87 |
| maartenwut/eon95 | evyd13/eon95 |
| maartenwut/gh80_1800 | evyd13/gh80_1800 |
| maartenwut/gh80_3700 | evyd13/gh80_3700 |
| maartenwut/minitomic | evyd13/minitomic |
| maartenwut/mx5160 | evyd13/mx5160 |
| maartenwut/nt660 | evyd13/nt660 |
| maartenwut/omrontkl | evyd13/omrontkl |
| maartenwut/plain60 | evyd13/plain60 |
| maartenwut/pockettype | evyd13/pockettype |
| maartenwut/quackfire | evyd13/quackfire |
| maartenwut/solheim68 | evyd13/solheim68 |
| maartenwut/ta65 | evyd13/ta65 |
| maartenwut/wasdat | evyd13/wasdat |
| maartenwut/wasdat_code | evyd13/wasdat_code |
| maartenwut/wonderland | evyd13/wonderland |
#### Xelus Valor and Dawn60 Refactors ([#10512](https://github.com/qmk/qmk_firmware/pull/10512), [#10584](https://github.com/qmk/qmk_firmware/pull/10584))
The Valor and Dawn60 keyboards by Xelus22 both now require their revisions to be specified when compiling.
| Previous Name | New Name |
| :------------ | :---------------- |
| xelus/dawn60 | xelus/dawn60/rev1 |
| xelus/valor | xelus/valor/rev1 |
### Updated Keyboard Codebases :id=keyboard-updates
#### AEboards EXT65 Refactor ([#10820](https://github.com/qmk/qmk_firmware/pull/10820))
The EXT65 codebase has been reworked so keymaps can be used with either revision.
## Core Changes :id=core-changes
### Fixes :id=core-fixes
* Reconnect the USB if users wake up a computer from the keyboard to restore the USB state ([#10088](https://github.com/qmk/qmk_firmware/pull/10088))
* Fix cursor position bug in oled_write_raw functions ([#10800](https://github.com/qmk/qmk_firmware/pull/10800))
### Additions and Enhancements :id=core-additions
* Allow MATRIX_ROWS to be greater than 32 ([#10183](https://github.com/qmk/qmk_firmware/pull/10183))
* Add support for soft serial to ATmega32U2 ([#10204](https://github.com/qmk/qmk_firmware/pull/10204))
* Allow direct control of MIDI velocity value ([#9940](https://github.com/qmk/qmk_firmware/pull/9940))
* Joystick 16-bit support ([#10439](https://github.com/qmk/qmk_firmware/pull/10439))
* Allow encoder resolutions to be set per encoder ([#10259](https://github.com/qmk/qmk_firmware/pull/10259))
* Share button state from mousekey to pointing_device ([#10179](https://github.com/qmk/qmk_firmware/pull/10179))
* Add advanced/efficient RGB Matrix Indicators ([#8564](https://github.com/qmk/qmk_firmware/pull/8564))
* OLED display update interval support ([#10388](https://github.com/qmk/qmk_firmware/pull/10388))
* Per-Key Retro Tapping ([#10622](https://github.com/qmk/qmk_firmware/pull/10622))
* Allow backlight duty cycle limit ([#10260](https://github.com/qmk/qmk_firmware/pull/10260))
* Add step sequencer feature ([#9703](https://github.com/qmk/qmk_firmware/pull/9703))
* Added `add_oneshot_mods` & `del_oneshot_mods` ([#10549](https://github.com/qmk/qmk_firmware/pull/10549))
* Add AT90USB support for serial.c ([#10706](https://github.com/qmk/qmk_firmware/pull/10706))
* Auto shift: support repeats and early registration (#9826)
### Clean-ups and Optimizations :id=core-optimizations
* Haptic and solenoid cleanup ([#9700](https://github.com/qmk/qmk_firmware/pull/9700))
* XD75 cleanup ([#10524](https://github.com/qmk/qmk_firmware/pull/10524))
* Minor change to behavior allowing display updates to continue between task ticks ([#10750](https://github.com/qmk/qmk_firmware/pull/10750))
* Change some GPIO manipulations in matrix.c to be atomic ([#10491](https://github.com/qmk/qmk_firmware/pull/10491))
* combine repeated lines of code for ATmega32U2, ATmega16U2, ATmega328 and ATmega328P ([#10837](https://github.com/qmk/qmk_firmware/pull/10837))
* Remove references to HD44780 ([#10735](https://github.com/qmk/qmk_firmware/pull/10735))
## QMK Infrastructure and Internals :id=qmk-internals
* Add ability to build a subset of all keyboards based on platform. ([#10420](https://github.com/qmk/qmk_firmware/pull/10420))
* Initialise EEPROM drivers at startup, instead of upon first execution ([#10438](https://github.com/qmk/qmk_firmware/pull/10438))
* Make bootloader_jump weak for ChibiOS ([#10417](https://github.com/qmk/qmk_firmware/pull/10417))
* Support for STM32 GPIOF,G,H,I,J,K ([#10206](https://github.com/qmk/qmk_firmware/pull/10206))
* Add milc as a dependency and remove the installed milc ([#10563](https://github.com/qmk/qmk_firmware/pull/10563))
* ChibiOS upgrade: early init conversions ([#10214](https://github.com/qmk/qmk_firmware/pull/10214))
* ChibiOS upgrade: configuration file migrator ([#9952](https://github.com/qmk/qmk_firmware/pull/9952))
* Add definition based on currently-selected serial driver. ([#10716](https://github.com/qmk/qmk_firmware/pull/10716))
* Allow for modification of output RGB values when using rgblight/rgb_matrix. ([#10638](https://github.com/qmk/qmk_firmware/pull/10638))
* Allow keyboards/keymaps to execute code at each main loop iteration ([#10530](https://github.com/qmk/qmk_firmware/pull/10530))
* qmk cformat ([#10767](https://github.com/qmk/qmk_firmware/pull/10767))
* Add a Make variable to easily enable DEBUG_MATRIX_SCAN_RATE on the command line ([#10824](https://github.com/qmk/qmk_firmware/pull/10824))
* update Chibios OS USB for the OTG driver ([#8893](https://github.com/qmk/qmk_firmware/pull/8893))
* Fixup version.h writing when using `SKIP_VERSION=yes` ([#10972](https://github.com/qmk/qmk_firmware/pull/10972), [#10974](https://github.com/qmk/qmk_firmware/pull/10974))
* Rename ledmatrix.h to match .c file ([#7949](https://github.com/qmk/qmk_firmware/pull/7949))
* Split RGB_MATRIX_ENABLE into _ENABLE and _DRIVER ([#10231](https://github.com/qmk/qmk_firmware/pull/10231))
* Split LED_MATRIX_ENABLE into _ENABLE and _DRIVER ([#10840](https://github.com/qmk/qmk_firmware/pull/10840))

View File

@@ -9,35 +9,24 @@
## What is QMK Firmware?
QMK (*Quantum Mechanical Keyboard*) is an open source community centered around developing computer input devices. The community encompasses all sorts of input devices, such as keyboards, mice, and MIDI devices. A core group of collaborators maintains [QMK Firmware](https://github.com/qmk/qmk_firmware), [QMK Configurator](https://config.qmk.fm), [QMK Toolbox](https://github.com/qmk/qmk_toolbox), [qmk.fm](https://qmk.fm), and this documentation with the help of community members like you.
QMK (*Quantum Mechanical Keyboard*) is an open source community that maintains QMK Firmware, QMK Toolbox, qmk.fm, and these docs. QMK Firmware is a keyboard firmware based on the [tmk\_keyboard](http://github.com/tmk/tmk_keyboard) with some useful features for Atmel AVR controllers, and more specifically, the [OLKB product line](http://olkb.com), the [ErgoDox EZ](http://www.ergodox-ez.com) keyboard, and the [Clueboard product line](http://clueboard.co/). It has also been ported to ARM chips using ChibiOS. You can use it to power your own hand-wired or custom keyboard PCB.
## Get Started
## How to Get It
Totally new to QMK? There are two ways to get started:
If you plan on contributing a keymap, keyboard, or features to QMK, the easiest thing to do is [fork the repo through Github](https://github.com/qmk/qmk_firmware#fork-destination-box), and clone your repo locally to make your changes, push them, then open a [Pull Request](https://github.com/qmk/qmk_firmware/pulls) from your fork.
* Basic: [QMK Configurator](https://config.qmk.fm)
* Just select your keyboard from the dropdown and program your keyboard.
* We have an [introductory video](https://www.youtube.com/watch?v=-imgglzDMdY) you can watch.
* There is also an overview [document you can read](newbs_building_firmware_configurator.md).
* Advanced: [Use The Source](newbs.md)
* More powerful, but harder to use
Otherwise, you can clone it directly with `git clone https://github.com/qmk/qmk_firmware`. Do not download the zip or tar files; a git repository is required to download the submodules in order to compile.
## Make It Yours
## How to Compile
QMK has lots of features to explore, and a good deal of reference documentation to dig through. Most features are taken advantage of by modifying your [keymap](keymap.md), and changing the [keycodes](keycodes.md).
Before you are able to compile, you'll need to [install an environment](getting_started_build_tools.md) for AVR or/and ARM development. Once that is complete, you'll use the `make` command to build a keyboard and keymap with the following notation:
## Need help?
make planck/rev4:default
Check out the [support page](support.md) to see how you can get help using QMK.
This would build the `rev4` revision of the `planck` with the `default` keymap. Not all keyboards have revisions (also called subprojects or folders), in which case, it can be omitted:
## Give Back
make preonic:default
There are a lot of ways you can contribute to the QMK Community. The easiest way to get started is to use it and spread the word to your friends.
## How to Customize
* Help people out on our forums and chat rooms:
* [/r/olkb](https://www.reddit.com/r/olkb/)
* [Discord Server](https://discord.gg/Uq7gcHh)
* Contribute to our documentation by clicking "Edit This Page" at the bottom
* [Translate our documentation into your language](translating.md)
* [Report a bug](https://github.com/qmk/qmk_firmware/issues/new/choose)
* [Open a Pull Request](contributing.md)
QMK has lots of [features](features.md) to explore, and a good deal of [reference documentation](http://docs.qmk.fm) to dig through. Most features are taken advantage of by modifying your [keymap](keymap.md), and changing the [keycodes](keycodes.md).

View File

@@ -1,183 +1,130 @@
* Tutorial
* [Introduction](newbs.md)
* [Setup](newbs_getting_started.md)
* [Complete Newbs Guide](newbs.md)
* [Getting Started](newbs_getting_started.md)
* [Building Your First Firmware](newbs_building_firmware.md)
* [Flashing Firmware](newbs_flashing.md)
* [Testing and Debugging](newbs_testing_debugging.md)
* [Getting Help/Support](support.md)
* [Other Resources](newbs_learn_more_resources.md)
* [Syllabus](syllabus.md)
* [Best Git Practices](newbs_git_best_practices.md)
* [Using Your Fork's Master](newbs_git_using_your_master_branch.md)
* [Resolving Merge Conflicts](newbs_git_resolving_merge_conflicts.md)
* [Resynchronizing a Branch](newbs_git_resynchronize_a_branch.md)
* [Learning Resources](newbs_learn_more_resources.md)
* FAQs
* [QMK Basics](README.md)
* [QMK Introduction](getting_started_introduction.md)
* [QMK CLI](cli.md)
* [QMK CLI Config](cli_configuration.md)
* [Contributing to QMK](contributing.md)
* [How to Use Github](getting_started_github.md)
* [Getting Help](getting_started_getting_help.md)
* [Breaking Changes](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
* [2019 Aug 30](ChangeLog/20190830.md)
* [FAQ](faq.md)
* [General FAQ](faq_general.md)
* [Build/Compile QMK](faq_build.md)
* [Debugging/Troubleshooting QMK](faq_debug.md)
* [Keymap FAQ](faq_keymap.md)
* [Keymap](faq_keymap.md)
* [Driver Installation with Zadig](driver_installation_zadig.md)
* Detailed Guides
* [Install Build Tools](getting_started_build_tools.md)
* [Vagrant Guide](getting_started_vagrant.md)
* [Build/Compile Instructions](getting_started_make_guide.md)
* [Flashing Firmware](flashing.md)
* [Customizing Functionality](custom_quantum_functions.md)
* [Keymap Overview](keymap.md)
* [Hardware](hardware.md)
* [Compatible Microcontrollers](compatible_microcontrollers.md)
* [AVR Processors](hardware_avr.md)
* [Drivers](hardware_drivers.md)
* Reference
* [Keyboard Guidelines](hardware_keyboard_guidelines.md)
* [Config Options](config_options.md)
* [Keycodes](keycodes.md)
* [Coding Conventions - C](coding_conventions_c.md)
* [Coding Conventions - Python](coding_conventions_python.md)
* [Documentation Best Practices](documentation_best_practices.md)
* [Documentation Templates](documentation_templates.md)
* [Glossary](reference_glossary.md)
* [Unit Testing](unit_testing.md)
* [Useful Functions](ref_functions.md)
* [Configurator Support](reference_configurator_support.md)
* [info.json Format](reference_info_json.md)
* [Python CLI Development](cli_development.md)
* Configurator
* [Overview](newbs_building_firmware_configurator.md)
* [Step by Step](configurator_step_by_step.md)
* [Troubleshooting](configurator_troubleshooting.md)
* QMK API
* [Overview](api_overview.md)
* [API Documentation](api_docs.md)
* [KLE To info.json](kle2json_guide.md)
* [Keyboard Support](reference_configurator_support.md)
* [Adding Default Keymaps](configurator_default_keymaps.md)
* [Features](features.md)
* [Basic Keycodes](keycodes_basic.md)
* [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md)
* [Quantum Keycodes](quantum_keycodes.md)
* [Advanced Keycodes](feature_advanced_keycodes.md)
* [Audio](feature_audio.md)
* [Auto Shift](feature_auto_shift.md)
* [Backlight](feature_backlight.md)
* [Bluetooth](feature_bluetooth.md)
* [Bootmagic](feature_bootmagic.md)
* [Combos](feature_combo.md)
* [Command](feature_command.md)
* [Debounce API](feature_debounce_type.md)
* [DIP Switch](feature_dip_switch.md)
* [Dynamic Macros](feature_dynamic_macros.md)
* [Encoders](feature_encoders.md)
* [Grave Escape](feature_grave_esc.md)
* [Haptic Feedback](feature_haptic_feedback.md)
* [HD44780 LCD Controller](feature_hd44780.md)
* [Key Lock](feature_key_lock.md)
* [Layouts](feature_layouts.md)
* [Leader Key](feature_leader_key.md)
* [LED Matrix](feature_led_matrix.md)
* [Macros](feature_macros.md)
* [Mouse Keys](feature_mouse_keys.md)
* [OLED Driver](feature_oled_driver.md)
* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys)
* [Pointing Device](feature_pointing_device.md)
* [PS/2 Mouse](feature_ps2_mouse.md)
* [RGB Lighting](feature_rgblight.md)
* [RGB Matrix](feature_rgb_matrix.md)
* [Space Cadet](feature_space_cadet.md)
* [Split Keyboard](feature_split_keyboard.md)
* [Stenography](feature_stenography.md)
* [Swap Hands](feature_swap_hands.md)
* [Tap Dance](feature_tap_dance.md)
* [Terminal](feature_terminal.md)
* [Thermal Printer](feature_thermal_printer.md)
* [Unicode](feature_unicode.md)
* [Userspace](feature_userspace.md)
* [Velocikey](feature_velocikey.md)
* CLI
* [Overview](cli.md)
* [Configuration](cli_configuration.md)
* [Commands](cli_commands.md)
* For Makers and Modders
* [Hand Wiring Guide](hand_wire.md)
* [ISP Flashing Guide](isp_flashing_guide.md)
* [ARM Debugging Guide](arm_debugging.md)
* [ADC Driver](adc_driver.md)
* [I2C Driver](i2c_driver.md)
* [WS2812 Driver](ws2812_driver.md)
* [EEPROM Driver](eeprom_driver.md)
* [GPIO Controls](internals_gpio_control.md)
* [Custom Matrix](custom_matrix.md)
* [Proton C Conversion](proton_c_conversion.md)
* Using QMK
* Guides
* [Customizing Functionality](custom_quantum_functions.md)
* [Driver Installation with Zadig](driver_installation_zadig.md)
* [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)
* IDEs
* [Using Eclipse with QMK](other_eclipse.md)
* [Using VSCode with QMK](other_vscode.md)
* Git Best Practices
* [Introduction](newbs_git_best_practices.md)
* [Your Fork](newbs_git_using_your_master_branch.md)
* [Merge Conflicts](newbs_git_resolving_merge_conflicts.md)
* [Fixing Your Branch](newbs_git_resynchronize_a_branch.md)
* Keyboard Building
* [Hand Wiring Guide](hand_wire.md)
* [ISP Flashing Guide](isp_flashing_guide.md)
* For a Deeper Understanding
* [How Keyboards Work](how_keyboards_work.md)
* [Understanding QMK](understanding_qmk.md)
* Simple Keycodes
* [Full List](keycodes.md)
* [Basic Keycodes](keycodes_basic.md)
* [Language-Specific Keycodes](reference_keymap_extras.md)
* [Modifier Keys](feature_advanced_keycodes.md)
* [Quantum Keycodes](quantum_keycodes.md)
* Other Topics
* [Using Eclipse with QMK](other_eclipse.md)
* [Using VSCode with QMK](other_vscode.md)
* [Support](support.md)
* [Translating the QMK Docs](translating.md)
* Advanced Keycodes
* [Command](feature_command.md)
* [Dynamic Macros](feature_dynamic_macros.md)
* [Grave Escape](feature_grave_esc.md)
* [Leader Key](feature_leader_key.md)
* [Mod-Tap](mod_tap.md)
* [Macros](feature_macros.md)
* [Mouse Keys](feature_mouse_keys.md)
* [Space Cadet Shift](feature_space_cadet.md)
* [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md)
* Software Features
* [Auto Shift](feature_auto_shift.md)
* [Combos](feature_combo.md)
* [Debounce API](feature_debounce_type.md)
* [Key Lock](feature_key_lock.md)
* [Layers](feature_layers.md)
* [One Shot Keys](one_shot_keys.md)
* [Pointing Device](feature_pointing_device.md)
* [Raw HID](feature_rawhid.md)
* [Sequencer](feature_sequencer.md)
* [Swap Hands](feature_swap_hands.md)
* [Tap Dance](feature_tap_dance.md)
* [Tap-Hold Configuration](tap_hold.md)
* [Terminal](feature_terminal.md)
* [Unicode](feature_unicode.md)
* [Userspace](feature_userspace.md)
* [WPM Calculation](feature_wpm.md)
* Hardware Features
* Displays
* [HD44780 LCD Controller](feature_hd44780.md)
* [OLED Driver](feature_oled_driver.md)
* Lighting
* [Backlight](feature_backlight.md)
* [LED Matrix](feature_led_matrix.md)
* [RGB Lighting](feature_rgblight.md)
* [RGB Matrix](feature_rgb_matrix.md)
* [Audio](feature_audio.md)
* [Bluetooth](feature_bluetooth.md)
* [Bootmagic](feature_bootmagic.md)
* [Custom Matrix](custom_matrix.md)
* [DIP Switch](feature_dip_switch.md)
* [Encoders](feature_encoders.md)
* [Haptic Feedback](feature_haptic_feedback.md)
* [Joystick](feature_joystick.md)
* [LED Indicators](feature_led_indicators.md)
* [Proton C Conversion](proton_c_conversion.md)
* [PS/2 Mouse](feature_ps2_mouse.md)
* [Split Keyboard](feature_split_keyboard.md)
* [Stenography](feature_stenography.md)
* [Thermal Printer](feature_thermal_printer.md)
* [Velocikey](feature_velocikey.md)
* Developing QMK
* [PR Checklist](pr_checklist.md)
* Breaking Changes
* [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
* History
* [2020 Nov 28](ChangeLog/20201128.md)
* [2020 Aug 29](ChangeLog/20200829.md)
* [2020 May 30](ChangeLog/20200530.md)
* [2020 Feb 29](ChangeLog/20200229.md)
* [2019 Aug 30](ChangeLog/20190830.md)
* C Development
* [ARM Debugging Guide](arm_debugging.md)
* [AVR Processors](hardware_avr.md)
* [Coding Conventions](coding_conventions_c.md)
* [Compatible Microcontrollers](compatible_microcontrollers.md)
* [Drivers](hardware_drivers.md)
* [ADC Driver](adc_driver.md)
* [I2C Driver](i2c_driver.md)
* [SPI Driver](spi_driver.md)
* [WS2812 Driver](ws2812_driver.md)
* [EEPROM Driver](eeprom_driver.md)
* ['serial' Driver](serial_driver.md)
* [GPIO Controls](internals_gpio_control.md)
* [Keyboard Guidelines](hardware_keyboard_guidelines.md)
* Python Development
* [Coding Conventions](coding_conventions_python.md)
* [QMK CLI Development](cli_development.md)
* Configurator Development
* QMK API
* [Development Environment](api_development_environment.md)
* [Architecture Overview](api_development_overview.md)
* Hardware Platform Development
* Arm/ChibiOS
* [Selecting an MCU](platformdev_selecting_arm_mcu.md)
* [Early initialization](platformdev_chibios_earlyinit.md)
* QMK Reference
* [Contributing to QMK](contributing.md)
* [Translating the QMK Docs](translating.md)
* [Config Options](config_options.md)
* [Make Documentation](getting_started_make_guide.md)
* [Documentation Best Practices](documentation_best_practices.md)
* [Documentation Templates](documentation_templates.md)
* [Community Layouts](feature_layouts.md)
* [Unit Testing](unit_testing.md)
* [Useful Functions](ref_functions.md)
* [info.json Format](reference_info_json.md)
* For a Deeper Understanding
* [How Keyboards Work](how_keyboards_work.md)
* [How a Matrix Works](how_a_matrix_works.md)
* [Understanding QMK](understanding_qmk.md)
* QMK Internals (In Progress)
* [Defines](internals_defines.md)
* [Input Callback Reg](internals_input_callback_reg.md)
* [Midi Device](internals_midi_device.md)
* [Midi Device Setup Process](internals_midi_device_setup_process.md)
* [Midi Util](internals_midi_util.md)
* [Send Functions](internals_send_functions.md)
* [Sysex Tools](internals_sysex_tools.md)
* QMK Internals (In Progress)
* [Defines](internals_defines.md)
* [Input Callback Reg](internals_input_callback_reg.md)
* [Midi Device](internals_midi_device.md)
* [Midi Device Setup Process](internals_midi_device_setup_process.md)
* [Midi Util](internals_midi_util.md)
* [Send Functions](internals_send_functions.md)
* [Sysex Tools](internals_sysex_tools.md)

View File

@@ -2,7 +2,7 @@
QMK can leverage the Analog-to-Digital Converter (ADC) on supported MCUs to measure voltages on certain pins. This can be useful for implementing things such as battery level indicators for Bluetooth keyboards, or volume controls using a potentiometer, as opposed to a [rotary encoder](feature_encoders.md).
This driver currently supports both AVR and a limited selection of ARM devices. The values returned are 10-bit integers (0-1023) mapped between 0V and VCC (usually 5V or 3.3V for AVR, 3.3V only for ARM), however on ARM there is more flexibility in control of operation through `#define`s if you need more precision.
This driver is currently AVR-only. The values returned are 10-bit integers (0-1023) mapped between 0V and VCC (usually 5V or 3.3V).
## Usage
@@ -20,9 +20,7 @@ Then place this include at the top of your code:
## Channels
### AVR
|Channel|AT90USB64/128|ATmega16/32U4|ATmega32A|ATmega328/P|
|Channel|AT90USB64/128|ATmega16/32U4|ATmega32A|ATmega328P|
|-------|-------------|-------------|---------|----------|
|0 |`F0` |`F0` |`A0` |`C0` |
|1 |`F1` |`F1` |`A1` |`C1` |
@@ -39,112 +37,14 @@ Then place this include at the top of your code:
|12 | |`B5` | | |
|13 | |`B6` | | |
<sup>\* The ATmega328/P possesses two extra ADC channels; however, they are not present on the DIP pinout, and are not shared with GPIO pins. You can use `adc_read()` directly to gain access to these.</sup>
### ARM
Note that some of these pins are doubled-up on ADCs with the same channel. This is because the pins can be used for either ADC.
Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-indexed, whereas the F3 has 4 ADCs and the channels are 1-indexed. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation.
|ADC|Channel|STM32F0xx|STM32F3xx|
|---|-------|---------|---------|
|1 |0 |`A0` | |
|1 |1 |`A1` |`A0` |
|1 |2 |`A2` |`A1` |
|1 |3 |`A3` |`A2` |
|1 |4 |`A4` |`A3` |
|1 |5 |`A5` |`F4` |
|1 |6 |`A6` |`C0` |
|1 |7 |`A7` |`C1` |
|1 |8 |`B0` |`C2` |
|1 |9 |`B1` |`C3` |
|1 |10 |`C0` |`F2` |
|1 |11 |`C1` | |
|1 |12 |`C2` | |
|1 |13 |`C3` | |
|1 |14 |`C4` | |
|1 |15 |`C5` | |
|1 |16 | | |
|2 |1 | |`A4` |
|2 |2 | |`A5` |
|2 |3 | |`A6` |
|2 |4 | |`A7` |
|2 |5 | |`C4` |
|2 |6 | |`C0` |
|2 |7 | |`C1` |
|2 |8 | |`C2` |
|2 |9 | |`C3` |
|2 |10 | |`F2` |
|2 |11 | |`C5` |
|2 |12 | |`B2` |
|2 |13 | | |
|2 |14 | | |
|2 |15 | | |
|2 |16 | | |
|3 |1 | |`B1` |
|3 |2 | |`E9` |
|3 |3 | |`E13` |
|3 |4 | | |
|3 |5 | | |
|3 |6 | |`E8` |
|3 |7 | |`D10` |
|3 |8 | |`D11` |
|3 |9 | |`D12` |
|3 |10 | |`D13` |
|3 |11 | |`D14` |
|3 |12 | |`B0` |
|3 |13 | |`E7` |
|3 |14 | |`E10` |
|3 |15 | |`E11` |
|3 |16 | |`E12` |
|4 |1 | |`E14` |
|4 |2 | |`B12` |
|4 |3 | |`B13` |
|4 |4 | |`B14` |
|4 |5 | |`B15` |
|4 |6 | |`E8` |
|4 |7 | |`D10` |
|4 |8 | |`D11` |
|4 |9 | |`D12` |
|4 |10 | |`D13` |
|4 |11 | |`D14` |
|4 |12 | |`D8` |
|4 |13 | |`D9` |
|4 |14 | | |
|4 |15 | | |
|4 |16 | | |
<sup>\* The ATmega328P possesses two extra ADC channels; however, they are not present on the DIP pinout, and are not shared with GPIO pins. You can use `adc_read()` directly to gain access to these.</sup>
## Functions
### AVR
|Function |Description |
|----------------------------|-------------------------------------------------------------------------------------------------------------------|
|`analogReference(mode)` |Sets the analog voltage reference source. Must be one of `ADC_REF_EXTERNAL`, `ADC_REF_POWER` or `ADC_REF_INTERNAL`.|
|`analogReadPin(pin)` |Reads the value from the specified pin, eg. `F6` for ADC6 on the ATmega32U4. |
|`pinToMux(pin)` |Translates a given pin to a mux value. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|`analogRead(pin)` |Reads the value from the specified Arduino pin, eg. `4` for ADC6 on the ATmega32U4. |
|`analogReadPin(pin)` |Reads the value from the specified QMK pin, eg. `F6` for ADC6 on the ATmega32U4. |
|`pinToMux(pin)` |Translates a given QMK pin to a mux value. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|`adc_read(mux)` |Reads the value from the ADC according to the specified mux. See your MCU's datasheet for more information. |
### ARM
|Function |Description |
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|`analogReadPin(pin)` |Reads the value from the specified pin, eg. `A0` for channel 0 on the STM32F0 and ADC1 channel 1 on the STM32F3. Note that if a pin can be used for multiple ADCs, it will pick the lower numbered ADC for this function. eg. `C0` will be channel 6 of ADC 1 when it could be used for ADC 2 as well.|
|`analogReadPinAdc(pin, adc)`|Reads the value from the specified pin and ADC, eg. `C0, 1` will read from channel 6, ADC 2 instead of ADC 1. Note that the ADCs are 0-indexed for this function. |
|`pinToMux(pin)` |Translates a given pin to a channel and ADC combination. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|`adc_read(mux)` |Reads the value from the ADC according to the specified pin and ADC combination. See your MCU's datasheet for more information. |
## Configuration
## ARM
The ARM implementation of the ADC has a few additional options that you can override in your own keyboards and keymaps to change how it operates. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.
|`#define` |Type |Default |Description |
|---------------------|------|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|`ADC_CIRCULAR_BUFFER`|`bool`|`false` |If `true`, then the implementation will use a circular buffer. |
|`ADC_NUM_CHANNELS` |`int` |`1` |Sets the number of channels that will be scanned as part of an ADC operation. The current implementation only supports `1`. |
|`ADC_BUFFER_DEPTH` |`int` |`2` |Sets the depth of each result. Since we are only getting a 12-bit result by default, we set this to 2 bytes so we can contain our one value. This could be set to 1 if you opt for an 8-bit or lower result.|
|`ADC_SAMPLING_RATE` |`int` |`ADC_SMPR_SMP_1P5` |Sets the sampling rate of the ADC. By default, it is set to the fastest setting. |
|`ADC_RESOLUTION` |`int` |`ADC_CFGR1_RES_12BIT`|The resolution of your result. We choose 12 bit by default, but you can opt for 12, 10, 8, or 6 bit. |

View File

@@ -1,3 +0,0 @@
# Development Environment Setup
To setup a development stack head over to the [qmk_web_stack](https://github.com/qmk/qmk_web_stack).

View File

@@ -1,44 +0,0 @@
# QMK Compiler Development Guide
This page attempts to introduce developers to the QMK Compiler. It does not go into nitty gritty details- for that you should read code. What this will give you is a framework to hang your understanding on as you read the code.
# Overview
The QMK Compile API consists of a few movings parts:
![Architecture Diagram](https://raw.githubusercontent.com/qmk/qmk_api/master/docs/architecture.svg)
API Clients interact exclusively with the API service. This is where they submit jobs, check status, and download results. The API service inserts compile jobs into [Redis Queue](https://python-rq.org) and checks both RQ and S3 for the results of those jobs.
Workers fetch new compile jobs from RQ, compile them, and then upload the source and the binary to an S3 compatible storage engine.
# Workers
QMK Compiler Workers are responsible for doing the actual building. When a worker pulls a job from RQ it does several things to complete that job:
* Make a fresh qmk_firmware checkout
* Use the supplied layers and keyboard metadata to build a `keymap.c`
* Build the firmware
* Zip a copy of the source
* Upload the firmware, source zip, and a metadata file to S3.
* Report the status of the job to RQ
# API Service
The API service is a relatively simple Flask application. There are a few main views you should understand.
## @app.route('/v1/compile', methods=['POST'])
This is the main entrypoint for the API. A client's interaction starts here. The client POST's a JSON document describing their keyboard, and the API does some (very) basic validation of that JSON before submitting the compile job.
## @app.route('/v1/compile/&lt;string:job_id&gt;', methods=['GET'])
This is the most frequently called endpoint. It pulls the job details from redis, if they're still available, or the cached job details on S3 if they're not.
## @app.route('/v1/compile/&lt;string:job_id&gt;/download', methods=['GET'])
This method allows users to download the compiled firmware file.
## @app.route('/v1/compile/&lt;string:job_id&gt;/source', methods=['GET'])
This method allows users to download the source for their firmware.

View File

@@ -1,68 +0,0 @@
# QMK API
This page describes using the QMK API. If you are an application developer you can use this API to compile firmware for any [QMK](https://qmk.fm) Keyboard.
## Overview
This service is an asynchronous API for compiling custom keymaps. You POST some JSON to the API, periodically check the status, and when your firmware has finished compiling you can download the resulting firmware and (if desired) source code for that firmware.
#### Example JSON Payload:
```json
{
"keyboard": "clueboard/66/rev2",
"keymap": "my_awesome_keymap",
"layout": "LAYOUT_all",
"layers": [
["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_RO","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_MHEN","KC_SPC","KC_SPC","KC_HENK","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"],
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SLCK","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","RESET","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
]
}
```
As you can see the payload describes all aspects of a keyboard necessary to create and generate a firmware. Each layer is a single list of QMK keycodes the same length as the keyboard's `LAYOUT` macro. If a keyboard supports mulitple `LAYOUT` macros you can specify which macro to use.
## Submitting a Compile Job
To compile your keymap into a firmware simply POST your JSON to the `/v1/compile` endpoint. In the following example we've placed the JSON payload into a file named `json_data`.
```
$ curl -H "Content-Type: application/json" -X POST -d "$(< json_data)" http://api.qmk.fm/v1/compile
{
"enqueued": true,
"job_id": "ea1514b3-bdfc-4a7b-9b5c-08752684f7f6"
}
```
## Checking The Status
After submitting your keymap you can check the status using a simple HTTP GET call:
```
$ curl http://api.qmk.fm/v1/compile/ea1514b3-bdfc-4a7b-9b5c-08752684f7f6
{
"created_at": "Sat, 19 Aug 2017 21:39:12 GMT",
"enqueued_at": "Sat, 19 Aug 2017 21:39:12 GMT",
"id": "f5f9b992-73b4-479b-8236-df1deb37c163",
"status": "running",
"result": null
}
```
This shows us that the job has made it through the queue and is currently running. There are 5 possible statuses:
* **failed**: Something about the compiling service has broken.
* **finished**: The compilation is complete and you should check `result` to see the results.
* **queued**: The keymap is waiting for a compilation server to become available.
* **running**: The compilation is in progress and should be complete soon.
* **unknown**: A serious error has occurred and you should [file a bug](https://github.com/qmk/qmk_compiler/issues).
## Examining Finished Results
Once your compile job has finished you'll check the `result` key. The value of this key is a hash containing several key bits of information:
* `firmware_binary_url`: A list of URLs for the the flashable firmware
* `firmware_keymap_url`: A list of URLs for the the `keymap.c`
* `firmware_source_url`: A list of URLs for the full firmware source code
* `output`: The stdout and stderr for this compile job. Errors will be found here.

View File

@@ -1,15 +0,0 @@
# QMK API
The QMK API provides an asynchronous API that Web and GUI tools can use to compile arbitrary keymaps for any keyboard supported by [QMK](http://qmk.fm/). The stock keymap template supports all QMK keycodes that do not require supporting C code. Keyboard maintainers can supply their own custom templates to enable more functionality.
## App Developers
If you are an app developer interested in using this API in your application you should head over to [Using The API](api_docs.md).
## Keyboard Maintainers
If you would like to enhance your keyboard's support in the QMK Compiler API head over to the [Keyboard Support](reference_configurator_support.md) section.
## Backend Developers
If you are interested in working on the API itself you should start by setting up a [Development Environment](api_development_environment.md), then check out [Hacking On The API](api_development_overview.md).

View File

@@ -0,0 +1,9 @@
# Becoming a QMK Collaborator
A QMK collaborator is a keyboard maker or designer that is interested in helping QMK grow and fully support their keyboard(s), and encouraging their users and customers to submit features, ideas, and keymaps. We're always looking to add more keyboards and collaborators, but we ask that they fulfill these requirements:
* **Have a PCB available for sale.** Unfortunately there's just too much variation and complications with handwired keyboards.
* **Maintain your keyboard in QMK.** This may just require an initial setup to get your keyboard working, but it could also include accommodating changes made to QMK's core that might break or render any custom code redundant.
* **Approve and merge keymap pull requests for your keyboard.** We like to encourage users to contribute their keymaps for others to see and work from when creating their own.
If you feel you meet these requirements, shoot us an email at hello@qmk.fm with an introduction and some links to your keyboard!

View File

@@ -6,30 +6,27 @@ The breaking change period is when we will merge PR's that change QMK in dangero
## What has been included in past Breaking Changes?
* [2020 Nov 28](ChangeLog/20201128.md)
* [2020 Aug 29](ChangeLog/20200829.md)
* [2020 May 30](ChangeLog/20200530.md)
* [2020 Feb 29](ChangeLog/20200229.md)
* [2019 Aug 30](ChangeLog/20190830.md)
## When is the next Breaking Change?
The next Breaking Change is scheduled for February 27, 2021.
The next Breaking Change is scheduled for May 30, 2020.
### Important Dates
* [x] 2020 Nov 28 - `develop` is created. Each push to `master` is subsequently merged to `develop`
* [ ] 2021 Jan 30 - `develop` closed to new PR's.
* [ ] 2021 Jan 30 - Call for testers.
* [ ] 2021 Feb 25 - `master` is locked, no PR's merged.
* [ ] 2021 Feb 27 - Merge `develop` to `master`.
* [ ] 2021 Feb 27 - `master` is unlocked. PR's can be merged again.
* [x] 2020 Feb 29 - `future` is created. It will be rebased weekly.
* [ ] 2020 May 2 - `future` closed to new PR's.
* [ ] 2020 May 2 - Call for testers.
* [ ] 2020 May 28 - `master` is locked, no PR's merged.
* [ ] 2020 May 30 - Merge `future` to `master`.
* [ ] 2020 May 30 - `master` is unlocked. PR's can be merged again.
## What changes will be included?
To see a list of breaking change candidates you can look at the [`breaking_change` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr). New changes might be added between now and when `develop` is closed, and a PR with that label applied is not guaranteed to be merged.
To see a list of breaking change candidates you can look at the [`breaking_change` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr). New changes might be added between now and when `future` is closed, and a PR with that label applied is not guaranteed to be merged.
If you want your breaking change to be included in this round you need to create a PR with the `breaking_change` label and have it accepted before `develop` closes. After `develop` closes no new breaking changes will be accepted.
If you want your breaking change to be included in this round you need to create a PR with the `breaking_change` label and have it accepted before `future` closes. After `future` closes no new breaking changes will be accepted.
Criteria for acceptance:
@@ -40,26 +37,41 @@ Criteria for acceptance:
This section documents various processes we use when running the Breaking Changes process.
## Creating the `develop` branch
## Rebase `future` from `master`
This happens immediately after the previous `develop` branch is merged.
This is run every Friday while `future` is open.
Process:
```
cd qmk_firmware
git checkout master
git pull --ff-only
git checkout future
git rebase master
git push --force
```
## Creating the `future` branch
This happens immediately after the previous `future` branch is merged.
* `qmk_firmware` git commands
* [ ] `git checkout master`
* [ ] `git pull --ff-only`
* [ ] `git checkout -b develop`
* [ ] `git checkout -b future`
* [ ] Edit `readme.md`
* [ ] Add a big notice at the top that this is a testing branch.
* [ ] Include a link to this document
* [ ] `git commit -m 'Branch point for <DATE> Breaking Change'`
* [ ] `git tag breakpoint_<YYYY>_<MM>_<DD>`
* [ ] `git tag <next_version>` # Prevent the breakpoint tag from confusing version incrementing
* [ ] `git push origin develop`
* [ ] `git push origin future`
* [ ] `git push --tags`
## 4 Weeks Before Merge
* `develop` is now closed to new PR's, only fixes for current PR's may be merged
* `future` is now closed to new PR's, only fixes for current PR's may be merged
* Post call for testers
* [ ] Discord
* [ ] GitHub PR
@@ -82,15 +94,15 @@ This happens immediately after the previous `develop` branch is merged.
## Day Of Merge
* `qmk_firmware` git commands
* [ ] `git checkout develop`
* [ ] `git checkout future`
* [ ] `git pull --ff-only`
* [ ] `git rebase origin/master`
* [ ] Edit `readme.md`
* [ ] Remove the notes about `develop`
* [ ] Remove the notes about `future`
* [ ] Roll up the ChangeLog into one file.
* [ ] `git commit -m 'Merge point for <DATE> Breaking Change'`
* [ ] `git push origin develop`
* GitHub Actions
* [ ] Create a PR for `develop`
* [ ] `git push origin future`
* Github Actions
* [ ] Create a PR for `future`
* [ ] Make sure travis comes back clean
* [ ] Merge `develop` PR
* [ ] Merge `future` PR

View File

@@ -27,7 +27,7 @@ If you are contributing core code, and the only reason it needs to go through br
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 &ndash; [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 &ndash; usually named `develop` &ndash; will be merged into the `master` branch, and `####` is the number of your pull request.
Your changelog should be located at `docs/ChangeLog/YYYYMMDD/PR####.md`, where `YYYYMMDD` is the date on which QMK's breaking change branch &ndash; usually named `future` &ndash; 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.

View File

@@ -1,34 +1,45 @@
# QMK CLI :id=qmk-cli
# QMK CLI
## Overview :id=overview
This page describes how to setup and use the QMK CLI.
# Overview
The QMK CLI makes building and working with QMK keyboards easier. We have provided a number of commands to simplify and streamline tasks such as obtaining and compiling the QMK firmware, creating keymaps, and more.
### Requirements :id=requirements
* [Global CLI](#global-cli)
* [Local CLI](#local-cli)
* [CLI Commands](#cli-commands)
QMK requires Python 3.6 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). These are installed automatically when you install the QMK CLI.
# Requirements
### Install Using Homebrew (macOS, some Linux) :id=install-using-homebrew
The CLI requires Python 3.5 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt).
# Global CLI
QMK provides an installable CLI that can be used to setup your QMK build environment, work with QMK, and which makes working with multiple copies of `qmk_firmware` easier. We recommend installing and updating this periodically.
## Install Using Homebrew (macOS, some Linux)
If you have installed [Homebrew](https://brew.sh) you can tap and install QMK:
```
brew install qmk/qmk/qmk
brew tap qmk/qmk
brew install qmk
export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware`
qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment
```
### Install Using pip :id=install-using-easy_install-or-pip
## Install Using easy_install or pip
If your system is not listed above you can install QMK manually. First ensure that you have Python 3.6 (or later) installed and have installed pip. Then install QMK with this command:
If your system is not listed above you can install QMK manually. First ensure that you have python 3.5 (or later) installed and have installed pip. Then install QMK with this command:
```
python3 -m pip install qmk
pip3 install qmk
export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware`
qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment
```
### Packaging For Other Operating Systems :id=packaging-for-other-operating-systems
## Packaging For Other Operating Systems
We are looking for people to create and maintain a `qmk` package for more operating systems. If you would like to create a package for your OS please follow these guidelines:
@@ -36,3 +47,269 @@ We are looking for people to create and maintain a `qmk` package for more operat
* Document why in a comment when you do deviate
* Install using a virtualenv
* Instruct the user to set the environment variable `QMK_HOME` to have the firmware source checked out somewhere other than `~/qmk_firmware`.
# Local CLI
If you do not want to use the global CLI there is a local CLI bundled with `qmk_firmware`. You can find it in `qmk_firmware/bin/qmk`. You can run the `qmk` command from any directory and it will always operate on that copy of `qmk_firmware`.
**Example**:
```
$ ~/qmk_firmware/bin/qmk hello
Ψ Hello, World!
```
## Local CLI Limitations
There are some limitations to the local CLI compared to the global CLI:
* The local CLI does not support `qmk setup` or `qmk clone`
* The local CLI always operates on the same `qmk_firmware` tree, even if you have multiple repositories cloned.
* The local CLI does not run in a virtualenv, so it's possible that dependencies will conflict
# CLI Commands
## `qmk cformat`
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>`
Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files.
**Usage for specified files**:
```
qmk cformat [file1] [file2] [...] [fileN]
```
**Usage for all core files**:
```
qmk cformat -a
```
**Usage for only changed files against origin/master**:
```
qmk cformat
```
**Usage for only changed files against branch_name**:
```
qmk cformat -b branch_name
```
## `qmk compile`
This command allows you to compile firmware from any directory. You can compile JSON exports from <https://config.qmk.fm>, compile keymaps in the repo, or compile the keyboard in the current working directory.
**Usage for Configurator Exports**:
```
qmk compile <configuratorExport.json>
```
**Usage for Keymaps**:
```
qmk compile -kb <keyboard_name> -km <keymap_name>
```
**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>`
```
qmk compile
```
**Example**:
```
$ qmk config compile.keymap=default
$ cd ~/qmk_firmware/keyboards/planck/rev6
$ qmk compile
Ψ Compiling keymap with make planck/rev6:default
...
```
or with optional keymap argument
```
$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4
$ qmk compile -km 66_iso
Ψ Compiling keymap with make clueboard/66/rev4:66_iso
...
```
or in keymap directory
```
$ cd ~/qmk_firmware/keyboards/gh60/satan/keymaps/colemak
$ qmk compile
Ψ Compiling keymap with make make gh60/satan:colemak
...
```
**Usage in Layout Directory**:
Must be under `qmk_firmware/layouts/`, and in a keymap folder.
```
qmk compile -kb <keyboard_name>
```
**Example**:
```
$ cd ~/qmk_firmware/layouts/community/60_ansi/mechmerlin-ansi
$ qmk compile -kb dz60
Ψ Compiling keymap with make dz60:mechmerlin-ansi
...
```
## `qmk flash`
This command is similar to `qmk compile`, but can also target a bootloader. The bootloader is optional, and is set to `:flash` by default.
To specify a different bootloader, use `-bl <bootloader>`. Visit <https://docs.qmk.fm/#/flashing>
for more details of the available bootloaders.
**Usage for Configurator Exports**:
```
qmk flash <configuratorExport.json> -bl <bootloader>
```
**Usage for Keymaps**:
```
qmk flash -kb <keyboard_name> -km <keymap_name> -bl <bootloader>
```
**Listing the Bootloaders**
```
qmk flash -b
```
## `qmk config`
This command lets you configure the behavior of QMK. For the full `qmk config` documentation see [CLI Configuration](cli_configuration.md).
**Usage**:
```
qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN]
```
## `qmk docs`
This command starts a local HTTP server which you can use for browsing or improving the docs. Default port is 8936.
**Usage**:
```
qmk docs [-p PORT]
```
## `qmk doctor`
This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to.
**Usage**:
```
qmk doctor [-y] [-n]
```
**Examples**:
Check your environment for problems and prompt to fix them:
qmk doctor
Check your environment and automatically fix any problems found:
qmk doctor -y
Check your environment and report problems only:
qmk doctor -n
## `qmk json-keymap`
Creates a keymap.c from a QMK Configurator export.
**Usage**:
```
qmk json-keymap [-o OUTPUT] filename
```
## `qmk kle2json`
This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite.
**Usage**:
```
qmk kle2json [-f] <filename>
```
**Examples**:
```
$ qmk kle2json kle.txt
☒ File info.json already exists, use -f or --force to overwrite.
```
```
$ qmk kle2json -f kle.txt -f
Ψ Wrote out to info.json
```
## `qmk list-keyboards`
This command lists all the keyboards currently defined in `qmk_firmware`
**Usage**:
```
qmk list-keyboards
```
## `qmk list-keymaps`
This command lists all the keymaps for a specified keyboard (and revision).
**Usage**:
```
qmk list-keymaps -kb planck/ez
```
## `qmk new-keymap`
This command creates a new keymap based on a keyboard's existing default keymap.
**Usage**:
```
qmk new-keymap [-kb KEYBOARD] [-km KEYMAP]
```
## `qmk pyformat`
This command formats python code in `qmk_firmware`.
**Usage**:
```
qmk pyformat
```
## `qmk pytest`
This command runs the python test suite. If you make changes to python code you should ensure this runs successfully.
**Usage**:
```
qmk pytest
```

View File

@@ -1,357 +0,0 @@
# QMK CLI Commands
# User Commands
## `qmk compile`
This command allows you to compile firmware from any directory. You can compile JSON exports from <https://config.qmk.fm>, compile keymaps in the repo, or compile the keyboard in the current working directory.
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
**Usage for Configurator Exports**:
```
qmk compile <configuratorExport.json>
```
**Usage for Keymaps**:
```
qmk compile -kb <keyboard_name> -km <keymap_name>
```
**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>`
```
qmk compile
```
**Usage for building all keyboards that support a specific keymap**:
```
qmk compile -kb all -km <keymap_name>
```
**Example**:
```
$ qmk config compile.keymap=default
$ cd ~/qmk_firmware/keyboards/planck/rev6
$ qmk compile
Ψ Compiling keymap with make planck/rev6:default
...
```
or with optional keymap argument
```
$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4
$ qmk compile -km 66_iso
Ψ Compiling keymap with make clueboard/66/rev4:66_iso
...
```
or in keymap directory
```
$ cd ~/qmk_firmware/keyboards/gh60/satan/keymaps/colemak
$ qmk compile
Ψ Compiling keymap with make make gh60/satan:colemak
...
```
**Usage in Layout Directory**:
Must be under `qmk_firmware/layouts/`, and in a keymap folder.
```
qmk compile -kb <keyboard_name>
```
**Example**:
```
$ cd ~/qmk_firmware/layouts/community/60_ansi/mechmerlin-ansi
$ qmk compile -kb dz60
Ψ Compiling keymap with make dz60:mechmerlin-ansi
...
```
## `qmk flash`
This command is similar to `qmk compile`, but can also target a bootloader. The bootloader is optional, and is set to `:flash` by default. To specify a different bootloader, use `-bl <bootloader>`. Visit the [Flashing Firmware](flashing.md) guide for more details of the available bootloaders.
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
**Usage for Configurator Exports**:
```
qmk flash <configuratorExport.json> -bl <bootloader>
```
**Usage for Keymaps**:
```
qmk flash -kb <keyboard_name> -km <keymap_name> -bl <bootloader>
```
**Listing the Bootloaders**
```
qmk flash -b
```
## `qmk config`
This command lets you configure the behavior of QMK. For the full `qmk config` documentation see [CLI Configuration](cli_configuration.md).
**Usage**:
```
qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN]
```
## `qmk doctor`
This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to.
**Usage**:
```
qmk doctor [-y] [-n]
```
**Examples**:
Check your environment for problems and prompt to fix them:
qmk doctor
Check your environment and automatically fix any problems found:
qmk doctor -y
Check your environment and report problems only:
qmk doctor -n
## `qmk info`
Displays information about keyboards and keymaps in QMK. You can use this to get information about a keyboard, show the layouts, display the underlying key matrix, or to pretty-print JSON keymaps.
**Usage**:
```
qmk info [-f FORMAT] [-m] [-l] [-km KEYMAP] [-kb KEYBOARD]
```
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
**Examples**:
Show basic information for a keyboard:
qmk info -kb planck/rev5
Show the matrix for a keyboard:
qmk info -kb ergodox_ez -m
Show a JSON keymap for a keyboard:
qmk info -kb clueboard/california -km default
## `qmk json2c`
Creates a keymap.c from a QMK Configurator export.
**Usage**:
```
qmk json2c [-o OUTPUT] filename
```
## `qmk c2json`
Creates a keymap.json from a keymap.c.
**Note:** Parsing C source files is not easy, therefore this subcommand may not work your keymap. In some cases not using the C pre-processor helps.
**Usage**:
```
qmk c2json -km KEYMAP -kb KEYBOARD [-q] [--no-cpp] [-o OUTPUT] filename
```
## `qmk lint`
Checks over a keyboard and/or keymap and highlights common errors, problems, and anti-patterns.
**Usage**:
```
qmk lint [-km KEYMAP] [-kb KEYBOARD] [--strict]
```
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
**Examples**:
Do a basic lint check:
qmk lint -kb rominronin/katana60/rev2
## `qmk list-keyboards`
This command lists all the keyboards currently defined in `qmk_firmware`
**Usage**:
```
qmk list-keyboards
```
## `qmk list-keymaps`
This command lists all the keymaps for a specified keyboard (and revision).
This command is directory aware. It will automatically fill in KEYBOARD if you are in a keyboard directory.
**Usage**:
```
qmk list-keymaps -kb planck/ez
```
## `qmk new-keymap`
This command creates a new keymap based on a keyboard's existing default keymap.
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
**Usage**:
```
qmk new-keymap [-kb KEYBOARD] [-km KEYMAP]
```
## `qmk clean`
This command cleans up the `.build` folder. If `--all` is passed, any .hex or .bin files present in the `qmk_firmware` directory will also be deleted.
**Usage**:
```
qmk clean [-a]
```
---
# Developer Commands
## `qmk cformat`
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>`
Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files.
**Usage for specified files**:
```
qmk cformat [file1] [file2] [...] [fileN]
```
**Usage for all core files**:
```
qmk cformat -a
```
**Usage for only changed files against origin/master**:
```
qmk cformat
```
**Usage for only changed files against branch_name**:
```
qmk cformat -b branch_name
```
## `qmk docs`
This command starts a local HTTP server which you can use for browsing or improving the docs. Default port is 8936.
**Usage**:
```
qmk docs [-p PORT]
```
## `qmk generate-docs`
This command allows you to generate QMK documentation locally. It can be uses for general browsing or improving the docs. External tools such as [serve](https://www.npmjs.com/package/serve) can be used to browse the generated files.
**Usage**:
```
qmk generate-docs
```
## `qmk generate-rgb-breathe-table`
This command generates a lookup table (LUT) header file for the [RGB Lighting](feature_rgblight.md) feature's breathing animation. Place this file in your keyboard or keymap directory as `rgblight_breathe_table.h` to override the default LUT in `quantum/`.
**Usage**:
```
qmk generate-rgb-breathe-table [-q] [-o OUTPUT] [-m MAX] [-c CENTER]
```
## `qmk kle2json`
This command allows you to convert [Keyboard-Layout-Editor.com](http://keyboard-layout-editor.com) layouts into `info.json` layouts. It will also create a `keymap.json` file for your layout. This saves a lot of time when setting up a new keyboard.
To use this command your KLE will need to follow a specific format. See [KLE To info.json](kle2json_guide.md) for more details.
**Usage**:
```
qmk kle2json -kb <keyboard> [-km KEYMAP] [-l LAYOUT] <filename-or-kle-id>
```
**Examples**:
With only a KLE id:
```
$ qmk kle2json -kb clueboard/new60 70aaa4bed76d0b2f67fd165641239552
Ψ Wrote file keyboards/clueboard/new60/info.json
Ψ Wrote file keyboards/clueboard/new60/keymaps/default/keymap.json
```
With a full URL:
```
$ qmk kle2json -kb clueboard/new60 'http://www.keyboard-layout-editor.com/#/gists/70aaa4bed76d0b2f67fd165641239552'
Ψ Wrote file keyboards/clueboard/new60/info.json
Ψ Wrote file keyboards/clueboard/new60/keymaps/default/keymap.json
```
## `qmk pyformat`
This command formats python code in `qmk_firmware`.
**Usage**:
```
qmk pyformat
```
## `qmk pytest`
This command runs the python test suite. If you make changes to python code you should ensure this runs successfully.
**Usage**:
```
qmk pytest
```

View File

@@ -4,7 +4,7 @@ This document explains how `qmk config` works.
# Introduction
Configuration for the QMK CLI is a key/value system. Each key consists of a subcommand and an argument name separated by a period. This allows for a straightforward and direct translation between config keys and the arguments they set.
Configuration for QMK CLI is a key/value system. Each key consists of a subcommand and an argument name separated by a period. This allows for a straightforward and direct translation between config keys and the arguments they set.
## Simple Example
@@ -108,7 +108,7 @@ compile.keymap: skully -> None
|-----|---------------|-------------|
| user.keyboard | None | The keyboard path (Example: `clueboard/66/rev4`) |
| user.keymap | None | The keymap name (Example: `default`) |
| user.name | None | The user's GitHub username. |
| user.name | None | The user's github username. |
# All Configuration Options

View File

@@ -6,18 +6,6 @@ This document has useful information for developers wishing to write new `qmk` s
The QMK CLI operates using the subcommand pattern made famous by git. The main `qmk` script is simply there to setup the environment and pick the correct entrypoint to run. Each subcommand is a self-contained module with an entrypoint (decorated by `@cli.subcommand()`) that performs some action and returns a shell returncode, or None.
## Developer mode:
If you intend to maintain keyboards and/or contribute to QMK, you can enable the CLI's "Developer" mode:
`qmk config user.developer=True`
This will allow you to see all available subcommands.
**Note:** You will have to install additional requirements:
```bash
python3 -m pip install -r requirements-dev.txt
```
# Subcommands
[MILC](https://github.com/clueboard/milc) is the CLI framework `qmk` uses to handle argument parsing, configuration, logging, and many other features. It lets you focus on writing your tool without wasting your time writing glue code.
@@ -44,7 +32,7 @@ def hello(cli):
First we import the `cli` object from `milc`. This is how we interact with the user and control the script's behavior. We use `@cli.argument()` to define a command line flag, `--name`. This also creates a configuration variable named `hello.name` (and the corresponding `user.name`) which the user can set so they don't have to specify the argument. The `cli.subcommand()` decorator designates this function as a subcommand. The name of the subcommand will be taken from the name of the function.
Once inside our function we find a typical "Hello, World!" program. We use `cli.log` to access the underlying [Logger Object](https://docs.python.org/3.6/library/logging.html#logger-objects), whose behavior is user controllable. We also access the value for name supplied by the user as `cli.config.hello.name`. The value for `cli.config.hello.name` will be determined by looking at the `--name` argument supplied by the user, if not provided it will use the value in the `qmk.ini` config file, and if neither of those is provided it will fall back to the default supplied in the `cli.argument()` decorator.
Once inside our function we find a typical "Hello, World!" program. We use `cli.log` to access the underlying [Logger Object](https://docs.python.org/3.5/library/logging.html#logger-objects), whose behavior is user controllable. We also access the value for name supplied by the user as `cli.config.hello.name`. The value for `cli.config.hello.name` will be determined by looking at the `--name` argument supplied by the user, if not provided it will use the value in the `qmk.ini` config file, and if neither of those is provided it will fall back to the default supplied in the `cli.argument()` decorator.
# User Interaction
@@ -56,13 +44,13 @@ There are two main methods for outputting text in a subcommand- `cli.log` and `c
You can use special tokens to colorize your text, to make it easier to understand the output of your program. See [Colorizing Text](#colorizing-text) below.
Both of these methods support built-in string formatting using python's [printf style string format operations](https://docs.python.org/3.6/library/stdtypes.html#old-string-formatting). You can use tokens such as `%s` and `%d` within your text strings then pass the values as arguments. See our Hello, World program above for an example.
Both of these methods support built-in string formatting using python's [printf style string format operations](https://docs.python.org/3.5/library/stdtypes.html#old-string-formatting). You can use tokens such as `%s` and `%d` within your text strings then pass the values as arguments. See our Hello, World program above for an example.
You should never use the format operator (`%`) directly, always pass values as arguments.
### Logging (`cli.log`)
The `cli.log` object gives you access to a [Logger Object](https://docs.python.org/3.6/library/logging.html#logger-objects). We have configured our log output to show the user a nice emoji for each log level (or the log level name if their terminal does not support unicode.) This way the user can tell at a glance which messages are most important when something goes wrong.
The `cli.log` object gives you access to a [Logger Object](https://docs.python.org/3.5/library/logging.html#logger-objects). We have configured our log output to show the user a nice emoji for each log level (or the log level name if their terminal does not support unicode.) This way the user can tell at a glance which messages are most important when something goes wrong.
The default log level is `INFO`. If the user runs `qmk -v <subcommand>` the default log level will be set to `DEBUG`.
@@ -210,7 +198,7 @@ Our tests can be found in `lib/python/qmk/tests/`. You will find both unit and i
If your PR does not include a comprehensive set of tests please add comments like this to your code so that other people know where they can help:
# TODO(unassigned/<your_github_username>): Write <unit|integration> tests
# TODO(unassigned/<yourGithubUsername>): Write <unit|integration> tests
We use [nose2](https://nose2.readthedocs.io/en/latest/getting_started.html) to run our tests. You can refer to the nose2 documentation for more details on what you can do in your test functions.

View File

@@ -20,11 +20,11 @@ Most of our style is pretty easy to pick up on, but right now it's not entirely
* We accept both forms of preprocessor if's: `#ifdef DEFINED` and `#if defined(DEFINED)`
* If you are not sure which to prefer use the `#if defined(DEFINED)` form.
* Do not change existing code from one style to the other, except when moving to a multiple condition `#if`.
* When deciding how (or if) to indent preprocessor directives, keep these points in mind:
* Readability is more important than consistency.
* Follow the file's existing style. If the file is mixed, follow the style that makes sense for the section you are modifying.
* When indenting, keep the hash at the start of the line and add whitespace between `#` and `if`, starting with 4 spaces after the `#`.
* You can follow the indention level of the surrounding C code, or preprocessor directives can have their own indentation levels. Choose the style that best communicates the intent of your code.
* Do not put whitespace between `#` and `if`.
* When deciding how (or if) to indent directives keep these points in mind:
* Readability is more important than consistency.
* Follow the file's existing style. If the file is mixed follow the style that makes sense for the section you are modifying.
* When choosing to indent you can follow the indention level of the surrounding C code, or preprocessor directives can have their own indent level. Choose the style that best communicates the intent of your code.
Here is an example for easy reference:

View File

@@ -2,7 +2,7 @@
Most of our style follows PEP8 with some local modifications to make things less nit-picky.
* We target Python 3.6 for compatability with all supported platforms.
* We target Python 3.5 for compatability with all supported platforms.
* We indent using four (4) spaces (soft tabs)
* We encourage liberal use of comments
* Think of them as a story describing the feature
@@ -317,7 +317,7 @@ At the time of this writing our tests are not very comprehensive. Looking at the
## Integration Tests
Integration tests can be found in `lib/python/qmk/tests/test_cli_commands.py`. This is where CLI commands are actually run and their overall behavior is verified. We use [`subprocess`](https://docs.python.org/3.6/library/subprocess.html#module-subprocess) to launch each CLI command and a combination of checking output and returncode to determine if the right thing happened.
Integration tests can be found in `lib/python/qmk/tests/test_cli_commands.py`. This is where CLI commands are actually run and their overall behavior is verified. We use [`subprocess`](https://docs.python.org/3.5/library/subprocess.html#module-subprocess) to launch each CLI command and a combination of checking output and returncode to determine if the right thing happened.
## Unit Tests

View File

@@ -14,7 +14,6 @@ Certain MCUs which do not have native USB will use [V-USB](https://www.obdev.at/
* [ATmega32A](https://www.microchip.com/wwwproducts/en/ATmega32A)
* [ATmega328P](https://www.microchip.com/wwwproducts/en/ATmega328P)
* [ATmega328](https://www.microchip.com/wwwproducts/en/ATmega328)
## ARM

View File

@@ -29,9 +29,7 @@ This level contains all of the options for that particular keymap. If you wish t
This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files, or anything besides this:
```c
#include "config_common.h"
```
#include "config_common.h"
## Hardware Options
@@ -45,6 +43,8 @@ This is a C header file that is one of the first things included, and will persi
* generally who/whatever brand produced the board
* `#define PRODUCT Board`
* the name of the keyboard
* `#define DESCRIPTION a keyboard`
* a short description of what the keyboard is
* `#define MATRIX_ROWS 5`
* the number of rows in your keyboard's matrix
* `#define MATRIX_COLS 15`
@@ -115,9 +115,9 @@ If you define these options you will disable the associated feature, which can s
* `#define NO_ACTION_ONESHOT`
* disable one-shot modifiers
* `#define NO_ACTION_MACRO`
* disable old-style macro handling using `MACRO()`, `action_get_macro()` _(deprecated)_
* disable old style macro handling: MACRO() & action_get_macro
* `#define NO_ACTION_FUNCTION`
* disable old-style function handling using `fn_actions`, `action_function()` _(deprecated)_
* disable calling of action_function() from the fn_actions array (deprecated)
## Features That Can Be Enabled
@@ -136,24 +136,22 @@ If you define these options you will enable the associated feature, which may in
* 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
* See [Retro Tapping](tap_hold.md#retro-tapping) for details
* `#define RETRO_TAPPING_PER_KEY`
* enables handling for per key `RETRO_TAPPING` settings
* See [Retro Tapping](feature_advanced_keycodes.md#retro-tapping) for details
* `#define TAPPING_TOGGLE 2`
* how many taps before triggering the toggle
* `#define PERMISSIVE_HOLD`
* makes tap and hold keys trigger the hold if another key is pressed before releasing, even if it hasn't hit the `TAPPING_TERM`
* See [Permissive Hold](tap_hold.md#permissive-hold) for details
* See [Permissive Hold](feature_advanced_keycodes.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
* See [Mod tap interrupt](feature_advanced_keycodes.md#ignore-mod-tap-interrupt) for details
* `#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
* enables handling for per key `IGNORE_MOD_TAP_INTERRUPT` settings
* `#define TAPPING_FORCE_HOLD`
* makes it possible to use a dual role key as modifier shortly after having been tapped
* See [Tapping Force Hold](tap_hold.md#tapping-force-hold)
* See [Hold after tap](feature_advanced_keycodes.md#tapping-force-hold)
* Breaks any Tap Toggle functionality (`TT` or the One Shot Tap Toggle)
* `#define TAPPING_FORCE_HOLD_PER_KEY`
* enables handling for per key `TAPPING_FORCE_HOLD` settings
@@ -192,15 +190,6 @@ If you define these options you will enable the associated feature, which may in
* pin the DI on the WS2812 is hooked-up to
* `#define RGBLIGHT_ANIMATIONS`
* run RGB animations
* `#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.
* `#define RGBLIGHT_MAX_LAYERS`
* Defaults to 8. Can be expanded up to 32 if more [lighting layers](feature_rgblight.md?id=lighting-layers) are needed.
* Note: Increasing the maximum will increase the firmware size and slow sync on split keyboards.
* `#define RGBLIGHT_LAYER_BLINK`
* Adds ability to [blink](feature_rgblight.md?id=lighting-layer-blink) a lighting layer for a specified number of milliseconds (e.g. to acknowledge an action).
* `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF`
* If defined, then [lighting layers](feature_rgblight?id=overriding-rgb-lighting-onoff-status) will be shown even if RGB Light is off.
* `#define RGBLED_NUM 12`
* number of LEDs
* `#define RGBLIGHT_SPLIT`
@@ -252,10 +241,7 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_HAND_PIN B7`
* For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
* `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>`
* The handedness is determined by using the intersection of the keyswitches in the key matrix, which does not exist. Normally, when this intersection is shorted (level low), it is considered left. If you define `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT`, it is determined to be right when the level is low.
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` and `SPLIT_HAND_MATRIX_GRID` are not defined)
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` is not defined)
* Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves.
* `#define MASTER_RIGHT`
@@ -328,9 +314,11 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
```
* `LAYOUTS`
* A list of [layouts](feature_layouts.md) this keyboard supports.
* `LINK_TIME_OPTIMIZATION_ENABLE`
* Enables Link Time Optimization (`LTO`) when compiling the keyboard. This makes the process take longer, but can significantly reduce the compiled size (and since the firmware is small, the added time is not noticeable). However, this will automatically disable the old Macros and Functions features automatically, as these break when `LTO` is enabled.
It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION`
* `LTO_ENABLE`
* Enables Link Time Optimization (LTO) when compiling the keyboard. This makes the process take longer, but it can significantly reduce the compiled size (and since the firmware is small, the added time is not noticeable).
However, this will automatically disable the legacy TMK Macros and Functions features, as these break when LTO is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION`. (Note: This does not affect QMK [Macros](feature_macros.md) and [Layers](feature_layers.md).)
* It has the same meaning as LINK_TIME_OPTIMIZATION_ENABLE. You can use `LTO_ENABLE` instead of `LINK_TIME_OPTIMIZATION_ENABLE`.
## AVR MCU Options
* `MCU = atmega32u4`
@@ -347,7 +335,7 @@ However, this will automatically disable the legacy TMK Macros and Functions fea
* `bootloadHID`
* `USBasp`
## Feature Options :id=feature-options
## Feature Options
Use these to enable or disable building certain features. The more you have enabled the bigger your firmware will be, and you run the risk of building a firmware too large for your MCU.
@@ -375,8 +363,10 @@ Use these to enable or disable building certain features. The more you have enab
* MIDI controls
* `UNICODE_ENABLE`
* Unicode
* `BLUETOOTH_ENABLE`
* Legacy option to Enable Bluetooth with the Adafruit EZ-Key HID. See BLUETOOTH
* `BLUETOOTH`
* Current options are AdafruitBLE, RN42
* Current options are AdafruitEzKey, AdafruitBLE, 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`

View File

@@ -1,193 +0,0 @@
# Adding Default Keymaps to QMK Configurator :id=adding-default-keymaps
This page covers how to add a default keymap for a keyboard to QMK Configurator.
## Technical Information :id=technical-information
QMK Configurator uses JSON as its native file format for keymaps. As much as possible, these should be kept such that they behave the same as running `make <keyboard>:default` from `qmk_firmware`.
Keymaps in this directory require four key-value pairs:
* `keyboard` (string)
* This is the name of the keyboard, the same as would be used when running a compile job through `make` (e.g. `make 1upkeyboards/1up60rgb:default`).
* `keymap` (string)
* Should be set to `default`.
* `layout` (string)
* This is the layout macro used by the default keymap.
* `layers` (array)
* The keymap itself. This key should contain one array per layer, which themselves should contain the keycodes that make up that layer.
Additionally, most keymaps contain a `commit` key. This key is not consumed by the API that back-stops QMK Configurator, but is used by Configurator's maintainers to tell which version of a keymap was used to create the JSON keymap in this repository. The value is the SHA of the last commit to modify a board's default `keymap.c` in the `qmk_firmware` repository. The SHA is found by checking out [the `master` branch of the `qmk/qmk_firmware` repository](https://github.com/qmk/qmk_firmware/tree/master/) and running `git log -1 --pretty=oneline -- keyboards/<keyboard>/keymaps/default/keymap.c` (use `keymap.json` if the keyboard in question has this file instead), which should return something similar to:
```shell
f14629ed1cd7c7ec9089604d64f29a99981558e8 Remove/migrate action_get_macro()s from default keymaps (#5625)
```
In this example, `f14629ed1cd7c7ec9089604d64f29a99981558e8` is the value that should be used for `commit`.
## Example :id=example
If one wished to add a default keymap for the H87a by Hineybush, one would run the `git log` command above against the H87a's default keymap in `qmk_firmware`:
```shell
user ~/qmk_firmware (master)
$ git log -1 --pretty=oneline master -- keyboards/hineybush/h87a/keymaps/default/keymap.c
ef8878fba5d3786e3f9c66436da63a560cd36ac9 Hineybush h87a lock indicators (#8237)
```
Now that we have the commit hash, we need the keymap (edited for readability):
```c
...
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_all(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_TRNS, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[1] = LAYOUT_all(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DEC, BL_INC,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_MNXT, KC_VOLD,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
};
```
The default keymap uses the `LAYOUT_all` macro, so that will be the value of the `layout` key. Compiled to a QMK Configurator JSON keymap, our resulting file should be:
```json
{
"keyboard": "hineybush/h87a",
"keymap": "default",
"commit": "ef8878fba5d3786e3f9c66436da63a560cd36ac9",
"layout": "LAYOUT_all",
"layers": [
[
"KC_ESC", "KC_F1", "KC_F2", "KC_F3", "KC_F4", "KC_F5", "KC_F6", "KC_F7", "KC_F8", "KC_F9", "KC_F10", "KC_F11", "KC_F12", "KC_PSCR", "KC_SLCK", "KC_PAUS",
"KC_GRV", "KC_1", "KC_2", "KC_3", "KC_4", "KC_5", "KC_6", "KC_7", "KC_8", "KC_9", "KC_0", "KC_MINS", "KC_EQL", "KC_BSPC", "KC_BSPC", "KC_INS", "KC_HOME", "KC_PGUP",
"KC_TAB", "KC_Q", "KC_W", "KC_E", "KC_R", "KC_T", "KC_Y", "KC_U", "KC_I", "KC_O", "KC_P", "KC_LBRC", "KC_RBRC", "KC_BSLS", "KC_DEL", "KC_END", "KC_PGDN",
"KC_CAPS", "KC_A", "KC_S", "KC_D", "KC_F", "KC_G", "KC_H", "KC_J", "KC_K", "KC_L", "KC_SCLN", "KC_QUOT", "KC_NUHS", "KC_ENT",
"KC_LSFT", "KC_NUBS", "KC_Z", "KC_X", "KC_C", "KC_V", "KC_B", "KC_N", "KC_M", "KC_COMM", "KC_DOT", "KC_SLSH", "KC_RSFT", "KC_TRNS", "KC_UP",
"KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "MO(1)", "KC_RGUI", "KC_RCTL", "KC_LEFT", "KC_DOWN", "KC_RGHT"
],
[
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DEC", "BL_INC",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_VOLU",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RESET", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY", "KC_MNXT", "KC_VOLD",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS"
]
]
}
```
The white space in the `layers` arrays have no effect on the functionality of the keymap, but are used to make these files easier for humans to read.
## Caveats :id=caveats
### Layers can only be referenced by number :id=layer-references
A common QMK convention is to name layers using a series of `#define`s, or an `enum` statement:
```c
enum layer_names {
_BASE,
_MEDIA,
_FN
};
```
This works in C, but for Configurator, you *must* use the layer's numeric index `MO(_FN)` would need to be `MO(2)` in the above example.
### No support for custom code of any kind :id=custom-code
Features that require adding functions to the keymap.c file, such as Tap Dance or Unicode, can not be compiled in Configurator **at all**. Even setting `TAP_DANCE_ENABLE = yes` in the `qmk_firmware` repository at the keyboard level will prevent Configurator from compiling **any** firmware for that keyboard. This is limited both by the API and the current spec of our JSON keymap format.
### Limited Support for Custom keycodes :id=custom-keycodes
There is a way to support custom keycodes: if the logic for a custom keycode is implemented at the keyboard level instead of the keymap level in qmk_firmware, that keycode *can* be used in Configurator and it *will* compile and work. Instead of using the following in your `keymap.c`:
```c
enum custom_keycodes {
MACRO_1 = SAFE_RANGE,
MACRO_2,
MACRO_3
};
...
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case MACRO_1:
if (record->event.pressed) {
SEND_STRING("This is macro #1.");
}
return false;
case MACRO_2:
if (record->event.pressed) {
SEND_STRING("This is macro #2.");
}
return false;
case MACRO_3:
if (record->event.pressed) {
SEND_STRING("This is macro #3.");
}
return false;
}
return true;
};
```
... add the keycode `enum` block to your keyboard's header file (`<keyboard>.h`) as follows (note that the `enum` is named `keyboard_keycodes` here):
```c
enum keyboard_keycodes {
MACRO_1 = SAFE_RANGE,
MACRO_2,
MACRO_3,
NEW_SAFE_RANGE // Important!
};
```
... then the logic to your `<keyboard>.c` through `process_record_kb()`:
```c
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case MACRO_1:
if (record->event.pressed) {
SEND_STRING("This is macro #1.");
}
return false;
case MACRO_2:
if (record->event.pressed) {
SEND_STRING("This is macro #2.");
}
return false;
case MACRO_3:
if (record->event.pressed) {
SEND_STRING("This is macro #3.");
}
return false;
}
return process_record_user(keycode, record);
};
```
Note the call to `process_record_user()` at the end. Additionally, users of the keyboard will need to use `NEW_SAFE_RANGE` instead of `SAFE_RANGE` if they wish to add their own custom keycodes at keymap level, beyond what is provided by the keyboard.
## Additional Reading :id=additional-reading
For QMK Configurator to support your keyboard, your keyboard must be present in the `master` branch of the `qmk_firmware` repository. For instructions on this, please see [Supporting Your Keyboard in QMK Configurator](reference_configurator_support.md).

View File

@@ -1,58 +0,0 @@
# QMK Configurator: Step by Step
This page describes the steps for building your firmware in QMK Configurator.
## Step 1: Select Your Keyboard
Click the drop down box and select the keyboard you want to create a keymap for.
?> If your keyboard has several versions, make sure you select the correct one.
I'll say that again because it's important:
!> **MAKE SURE YOU SELECT THE RIGHT VERSION!**
If your keyboard has been advertised to be powered by QMK but is not in the list, chances are a developer hasn't gotten to it yet or we haven't had a chance to merge it in yet. File an issue at [qmk_firmware](https://github.com/qmk/qmk_firmware/issues) requesting to support that particular keyboard, if there is no active [Pull Request](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) for it. There are also QMK powered keyboards that are in their manufacturer's own GitHub accounts. Double check for that as well. <!-- FIXME(skullydazed): This feels too wordy and I'm not sure we want to encourage these kinds of issues. Also, should we prompt them to bug the manufacutrer? -->
## Step 2: Select Your Keyboard Layout
Choose the layout that best represents the keymap you want to create. Some keyboards do not have enough layouts or correct layouts defined yet. They will be supported in the future.
!> Sometimes there isn't a layout that supports your exact build. In that case select `LAYOUT_all`.
## Step 3: Name Your Keymap
Call this keymap what you want.
?> If you are running into issues when compiling, it may be worth changing this name, as it may already exist in the QMK Firmware repo.
## Step 4: Define Your Keymap
Keycode Entry is accomplished in one of 3 ways:
1. Drag and drop
2. Clicking on an empty spot on the layout, then clicking the keycode you desire
3. Clicking on an empty spot on the layout, then pressing the physical key on your keyboard
?> Hover your mouse over a key and a short blurb will tell you what that keycode does. For a more verbose description please see:
* [Basic Keycode Reference](keycodes_basic.md)
* [Advanced Keycode Reference](feature_advanced_keycodes.md)
!> If your selected layout doesn't match your physical build leave the unused keys blank. If you're not sure which key is in use, for example you have a one backspace key but `LAYOUT_all` has 2 keys, put the same keycode in both locations.
## Step 5: Save Your Keymap for Future Changes
When you're satisfied with your keymap or just want to work on it later, press the `Export Keymap` button. It will save your keymap to your computer. You can then load this .json file in the future by pressing the `Import Keymap` button.
!> **CAUTION:** This is not the same type of .json file used for kbfirmware.com or any other tool. If you try to use this for those tools, or the .json from those tools with QMK Configurator, you will encounter problems.
## Step 6: Compile Your Firmware File
Press the green `Compile` button.
When the compilation is done, you will be able to press the green `Download Firmware` button.
## Next steps: Flashing Your Keyboard
Please refer to [Flashing Firmware](newbs_flashing.md).

View File

@@ -1,26 +0,0 @@
# Configurator Troubleshooting
## My .json file is not working
If the .json file was generated with QMK Configurator, congratulations you have stumbled upon a bug. File an issue at [qmk_configurator](https://github.com/qmk/qmk_configurator/issues).
If not... how did you miss the big bold message at the top saying not to use other .json files?
## There are extra spaces in my layout? What do I do?
If you're referring to having three spots for space bar, the best course of action is to just fill them all with Space. The same can be done for Backspace and Shift keys.
## What is the keycode for...
Please see:
* [Basic Keycode Reference](keycodes_basic.md)
* [Advanced Keycode Reference](feature_advanced_keycodes.md)
## It won't compile
Please double check the other layers of your keymap to make sure there are no random keys present.
## Problems and Bugs
We are always accepting customer requests and bug reports. Please file them at [qmk_configurator](https://github.com/qmk/qmk_configurator/issues).

View File

@@ -101,7 +101,7 @@ enum my_keycodes {
};
```
### Previewing the Documentation :id=previewing-the-documentation
### Previewing the Documentation
Before opening a pull request, you can preview your changes if you have set up the development environment by running this command from the `qmk_firmware/` folder:

View File

@@ -4,7 +4,7 @@ For a lot of people a custom keyboard is about more than sending button presses
This page does not assume any special knowledge about QMK, but reading [Understanding QMK](understanding_qmk.md) will help you understand what is going on at a more fundamental level.
## A Word on Core vs Keyboards vs Keymap :id=a-word-on-core-vs-keyboards-vs-keymap
## A Word on Core vs Keyboards vs Keymap
We have structured QMK as a hierarchy:
@@ -34,7 +34,7 @@ enum my_keycodes {
};
```
## Programming the Behavior of Any Keycode :id=programming-the-behavior-of-any-keycode
## Programming the Behavior of Any Keycode
When you want to override the behavior of an existing key, or define the behavior for a new key, you should use the `process_record_kb()` and `process_record_user()` functions. These are called by QMK during key processing before the actual key event is handled. If these functions return `true` QMK will process the keycodes as usual. That can be handy for extending the functionality of a key rather than replacing it. If these functions return `false` QMK will skip the normal key handling, and it will be up to you to send any key up or down events that are required.
@@ -57,7 +57,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case KC_ENTER:
// Play a tone when enter is pressed
if (record->event.pressed) {
PLAY_SONG(tone_qwerty);
PLAY_NOTE_ARRAY(tone_qwerty);
}
return true; // Let QMK send the enter press/release events
default:
@@ -88,6 +88,108 @@ keyrecord_t record {
}
```
# LED Control
QMK provides methods to read 5 of the LEDs defined in the HID spec:
* Num Lock
* Caps Lock
* Scroll Lock
* Compose
* Kana
There are two ways to get the lock LED state:
* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
* by calling `led_t host_keyboard_led_state()`
!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
Two more deprecated functions exist that provide the LED state as a `uint8_t`:
* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
* `uint8_t host_keyboard_leds()`
## `led_update_user()`
This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
return `false` when you would prefer not to run the code in `led_update_kb()`.
Some examples include:
- overriding the LEDs to use them for something else like layer indication
- return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
- play a sound when an LED turns on or off.
- return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead.
### Example `led_update_kb()` Implementation
```c
bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state);
if(res) {
// writePin sets the pin high for 1 and low for 0.
// In this example the pins are inverted, setting
// it low/0 turns it on, and high/1 turns the LED off.
// This behavior depends on whether the LED is between the pin
// and VCC or the pin and GND.
writePin(B0, !led_state.num_lock);
writePin(B1, !led_state.caps_lock);
writePin(B2, !led_state.scroll_lock);
writePin(B3, !led_state.compose);
writePin(B4, !led_state.kana);
}
return res;
}
```
### Example `led_update_user()` Implementation
This incomplete example would play a sound if Caps Lock is turned on or off. It returns `true`, because you also want the LEDs to maintain their state.
```c
#ifdef AUDIO_ENABLE
float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
#endif
bool led_update_user(led_t led_state) {
#ifdef AUDIO_ENABLE
static uint8_t caps_state = 0;
if (caps_state != led_state.caps_lock) {
led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
caps_state = led_state.caps_lock;
}
#endif
return true;
}
```
### `led_update_*` Function Documentation
* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
* Keymap: `bool led_update_user(led_t led_state)`
## `host_keyboard_led_state()`
Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
## Setting Physical LED State
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
### Ergodox Boards
The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).
# Keyboard Initialization Code
There are several steps in the keyboard initialization process. Depending on what you want to do, it will influence which function you should use.
@@ -185,14 +287,6 @@ This function gets called at every matrix scan, which is basically as often as t
You should use this function if you need custom matrix scanning code. It can also be used for custom status output (such as LEDs or a display) or other functionality that you want to trigger regularly even when the user isn't typing.
# Keyboard housekeeping
* Keyboard/Revision: `void housekeeping_task_kb(void)`
* Keymap: `void housekeeping_task_user(void)`
This function gets called at the end of all QMK processing, before starting the next iteration. You can safely assume that QMK has dealt with the last matrix scan at the time that these functions are invoked -- layer states have been updated, USB reports have been sent, LEDs have been updated, and displays have been drawn.
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.
# Keyboard Idling/Wake Code
@@ -219,13 +313,13 @@ void suspend_wakeup_init_user(void) {
* Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
* Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
# Layer Change Code :id=layer-change-code
# Layer Change Code
This runs code every time that the layers get changed. This can be useful for layer indication, or custom layer handling.
### Example `layer_state_set_*` Implementation
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example.
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example
```c
layer_state_t layer_state_set_user(layer_state_t state) {
@@ -249,11 +343,6 @@ layer_state_t layer_state_set_user(layer_state_t state) {
return state;
}
```
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.
### `layer_state_set_*` Function Documentation
* Keyboard/Revision: `layer_state_t layer_state_set_kb(layer_state_t state)`
@@ -349,7 +438,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case KC_ENTER:
// Play a tone when enter is pressed
if (record->event.pressed) {
PLAY_SONG(tone_qwerty);
PLAY_NOTE_ARRAY(tone_qwerty);
}
return true; // Let QMK send the enter press/release events
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
@@ -360,7 +449,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_state_set(layer_state); // then immediately update the layer color
}
}
return false;
return false; break;
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
if (user_config.rgb_layer_change) { // only if this is enabled
@@ -397,3 +486,56 @@ And you're done. The RGB layer indication will only work if you want it to. And
* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.
# Custom Tapping Term
By default, the tapping term and related options (such as `IGNORE_MOD_TAP_INTERRUPT`) are defined globally, and are not configurable by key. For most users, this is perfectly fine. But in some cases, dual function keys would be greatly improved by different timeout behaviors than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable timeout behaviors.
There are two configurable options to control per-key timeout behaviors:
- `TAPPING_TERM_PER_KEY`
- `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
You need to add `#define` lines to your `config.h` for each feature you want.
```
#define TAPPING_TERM_PER_KEY
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
```
## Example `get_tapping_term` Implementation
To change the `TAPPING_TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file:
```c
uint16_t get_tapping_term(uint16_t keycode) {
switch (keycode) {
case SFT_T(KC_SPC):
return TAPPING_TERM + 1250;
case LT(1, KC_GRV):
return 130;
default:
return TAPPING_TERM;
}
}
```
## Example `get_ignore_mod_tap_interrupt` Implementation
To change the `IGNORE_MOD_TAP_INTERRUPT` value based on the keycode, you'd want to add something like the following to your `keymap.c` file:
```c
bool get_ignore_mod_tap_interrupt(uint16_t keycode) {
switch (keycode) {
case SFT_T(KC_SPC):
return true;
default:
return false;
}
}
```
## `get_tapping_term` / `get_ignore_mod_tap_interrupt` Function Documentation
Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only user level functions are useful here, so no need to mark them as such.

View File

@@ -13,7 +13,7 @@ QMK (*Quantum Mechanical Keyboard*) ist eine Open-Source-Community, welche die Q
## Bezugsquelle für QMK
Wenn Du vorhast, deine Tastatur, Tastaturbelegung oder Features zu QMK beizusteuern, geht das am einfachsten, indem Du das [Repository auf GitHub](https://github.com/qmk/qmk_firmware#fork-destination-box) forkst, die Änderungen in deinem lokalen Repo vornimmst und anschließend einen [Pull Request](https://github.com/qmk/qmk_firmware/pulls) einreichst.
Wenn Du vorhast, deine Tastatur, Tastaturbelegung oder Features zu QMK beizusteuern, geht das am einfachsten, indem Du das [Repository auf Github](https://github.com/qmk/qmk_firmware#fork-destination-box) forkst, die Änderungen in deinem lokalen Repo vornimmst und anschließend einen [Pull Request](https://github.com/qmk/qmk_firmware/pulls) einreichst.
Ansonsten kannst Du es als [zip](https://github.com/qmk/qmk_firmware/zipball/master) oder [tar](https://github.com/qmk/qmk_firmware/tarball/master) herunterladen, oder es direkt via git klonen (`git clone git@github.com:qmk/qmk_firmware.git` bzw. `git clone https://github.com/qmk/qmk_firmware.git`).

View File

@@ -11,7 +11,7 @@
* [QMK CLI](de/cli.md)
* [QMK CLI Konfiguration](de/cli_configuration.md)
* [Zu QMK beitragen](de/contributing.md)
* [Anleitung für GitHub](de/getting_started_github.md)
* [Anleitung für Github](de/getting_started_github.md)
* [Nach Hilfe fragen](de/getting_started_getting_help.md)
* [Breaking Changes](de/breaking_changes.md)
@@ -77,7 +77,7 @@
* [Macros](de/feature_macros.md)
* [Mouse Keys](de/feature_mouse_keys.md)
* [OLED Driver](de/feature_oled_driver.md)
* [One Shot Keys](de/one_shot_keys.md)
* [One Shot Keys](de/feature_advanced_keycodes.md#one-shot-keys)
* [Pointing Device](de/feature_pointing_device.md)
* [PS/2 Mouse](de/feature_ps2_mouse.md)
* [RGB Lighting](de/feature_rgblight.md)
@@ -98,7 +98,6 @@
* [ISP Flashing Guide](de/isp_flashing_guide.md)
* [ARM Debugging Guide](de/arm_debugging.md)
* [I2C Driver](de/i2c_driver.md)
* [SPI Driver](de/spi_driver.md)
* [GPIO Controls](de/internals_gpio_control.md)
* [Proton C Conversion](de/proton_c_conversion.md)
@@ -109,7 +108,7 @@
* Andere Themen
* [Eclipse mit QMK](de/other_eclipse.md)
* [VSCode mit QMK](de/other_vscode.md)
* [Support](de/getting_started_getting_help.md)
* [Support](de/support.md)
* [Übersetzungen](de/translating.md)
* QMK Internals (In Progress)

View File

@@ -6,7 +6,7 @@ Git Ressourcen:
* [Gutes allgemeines Tutorial](https://www.codecademy.com/learn/learn-git) (auf Englisch)
* [Git spielerisch anhand von Beispielen lernen](https://learngitbranching.js.org/) (auf Englisch)
* [Mehr über den allgemeinen Umgang mit GitHub](getting_started_github.md)
* [Mehr über den allgemeinen Umgang mit Github](getting_started_github.md)
* [Mehr über Git im Bezug zu QMK](contributing.md)
Mehr über die Arbeit mit der Befehlszeile:

View File

@@ -41,9 +41,7 @@ Bevorzugst Du es lieber auf der Befehlszeile zu debuggen? Dafür eignet sich das
Manchmal ist es hilfreich Debug-Nachrichten innerhalb deines eigenen [Custom Codes](de/custom_quantum_functions.md) zu drucken. Das ist ziemlich einfach. Beginne damit `print.h` am Anfang deiner Datei zu inkludieren:
```c
#include "print.h"
```
#include <print.h>
Danach stehen dir verschiedene Druck-Funktionen zur Verfügung:

View File

@@ -61,4 +61,4 @@ This page describes my cool feature. You can use my cool feature to make coffee
|KC_SUGAR||Order Sugar|
```
Place your documentation into `docs/feature_<my_cool_feature>.md`, and add that file to the appropriate place in `docs/_summary.md`. If you have added any keycodes be sure to add them to `docs/keycodes.md` with a link back to your feature page.
Place your documentation into `docs/feature_<my_cool_feature>.md`, and add that file to the appropriate place in `docs/_sidebar.md`. If you have added any keycodes be sure to add them to `docs/keycodes.md` with a link back to your feature page.

View File

@@ -2,7 +2,7 @@
This page documents the templates you should use when submitting new Keymaps and Keyboards to QMK.
## Keymap `readme.md` Template :id=keyboard-readmemd-template
## Keymap `readme.md` Template
Most keymaps have an image depicting the layout. You can use [Keyboard Layout Editor](http://keyboard-layout-editor.com) to create an image. Upload it to [Imgur](http://imgur.com) or another hosting service, please do not include images in your Pull Request.

View File

@@ -4,7 +4,7 @@ QMK presents itself to the host as a regular HID keyboard device, and as such re
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the `qmk_install.sh` script will have already installed the drivers for you.
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2 or WSL, the `qmk_install.sh` script will have asked if you want it to install the drivers for you.
## Installation
@@ -14,11 +14,16 @@ Some keyboards may have specific instructions for entering the bootloader. For e
To put a device in bootloader mode with USBaspLoader, tap the `RESET` button while holding down the `BOOT` button.
Alternatively, hold `BOOT` while inserting the USB cable.
Zadig should automatically detect the bootloader device, but you may sometimes need to check **Options → List All Devices** and select the device from the dropdown instead.
Zadig will automatically detect the bootloader device. You may sometimes need to check **Options → List All Devices**.
- For keyboards with Atmel AVR MCUs, the bootloader will be named something similar to `ATm32U4DFU`, and have a Vendor ID of `03EB`.
- USBasp bootloaders will appear as `USBasp`, with a VID/PID of `16C0:05DC`.
- AVR keyboards flashed with the QMK-DFU bootloader will be named `<keyboard name> Bootloader` and will also have the VID `03EB`.
- For most ARM keyboards, it will be called `STM32 BOOTLOADER`, and have a VID/PID of `0483:DF11`.
!> If Zadig lists one or more devices with the `HidUsb` driver, your keyboard is probably not in bootloader mode. The arrow will be colored orange and you will be asked to confirm modifying a system driver. **Do not** proceed if this is the case!
If the arrow appears green, select the driver, and click **Install Driver**. See the [list of known bootloaders](#list-of-known-bootloaders) for the correct driver to install.
If the arrow appears green, select the driver, and click **Install Driver**. The `libusb-win32` driver will usually work for AVR, and `WinUSB` for ARM, but if you still cannot flash the board, try installing a different driver from the list. For flashing a USBaspLoader device via command line with msys2, the `libusbk` driver is recommended, otherwise `libusb-win32` will work fine if you are using QMK Toolbox for flashing.
![Zadig with a bootloader driver correctly installed](https://i.imgur.com/b8VgXzx.png)
@@ -38,40 +43,6 @@ Right-click it and hit **Uninstall device**. Make sure to tick **Delete the driv
![The Device Uninstall dialog, with the "delete driver" checkbox ticked](https://i.imgur.com/aEs2RuA.png)
Click **Action → Scan for hardware changes**. At this point, you should be able to type again. Double check in Zadig that the keyboard device(s) are using the `HidUsb` driver. If so, you're all done, and your board should be functional again! Otherwise, repeat the process until Zadig reports the correct driver.
Click **Action → Scan for hardware changes**. At this point, you should be able to type again. Double check in Zadig that the keyboard device(s) are using the `HidUsb` driver. If so, you're all done, and your board should be functional again!
?> A full reboot of your computer may sometimes be necessary at this point, to get Windows to pick up the new driver.
## List of Known Bootloaders
This is a list of known bootloader devices and their USB vendor and product IDs, as well as the correct driver to assign for flashing with QMK. Note that the usbser and HidUsb drivers are built in to Windows, and cannot be assigned with Zadig - if your device has an incorrect driver, you must use the Device Manager to uninstall it as described in the previous section.
The device name here is the name that appears in Zadig, and may not be what the Device Manager or QMK Toolbox displays.
|Bootloader |Device Name |VID/PID |Driver |
|-------------|------------------------------|--------------|-------|
|`atmel-dfu` |ATmega16u2 DFU |`03EB:2FEF` |libusb0|
|`atmel-dfu` |ATmega32U2 DFU |`03EB:2FF0` |libusb0|
|`atmel-dfu` |ATm16U4 DFU V1.0.2 |`03EB:2FF3` |libusb0|
|`atmel-dfu` |ATm32U4DFU |`03EB:2FF4` |libusb0|
|`atmel-dfu` |*none* (AT90USB64) |`03EB:2FF9` |libusb0|
|`atmel-dfu` |AT90USB128 DFU |`03EB:2FFB` |libusb0|
|`qmk-dfu` |(keyboard name) Bootloader |As `atmel-dfu`|libusb0|
|`halfkay` |*none* |`16C0:0478` |HidUsb |
|`caterina` |Pro Micro 3.3V |`1B4F:9203` |usbser |
|`caterina` |Pro Micro 5V |`1B4F:9205` |usbser |
|`caterina` |LilyPadUSB |`1B4F:9207` |usbser |
|`caterina` |Pololu A-Star 32U4 Bootloader |`1FFB:0101` |usbser |
|`caterina` |Arduino Leonardo |`2341:0036` |usbser |
|`caterina` |Arduino Micro |`2341:0037` |usbser |
|`caterina` |Adafruit Feather 32u4 |`239A:000C` |usbser |
|`caterina` |Adafruit ItsyBitsy 32u4 3V |`239A:000D` |usbser |
|`caterina` |Adafruit ItsyBitsy 32u4 5V |`239A:000E` |usbser |
|`caterina` |Arduino Leonardo |`2A03:0036` |usbser |
|`caterina` |Arduino Micro |`2A03:0037` |usbser |
|`bootloadHID`|HIDBoot |`16C0:05DF` |HidUsb |
|`USBasp` |USBasp |`16C0:05DC` |libusbK|
|`apm32-dfu` |APM32 DFU ISP Mode |`314B:0106` |WinUSB |
|`stm32-dfu` |STM32 BOOTLOADER |`0483:DF11` |WinUSB |
|`kiibohd` |Kiibohd DFU Bootloader |`1C11:B007` |WinUSB |
|`stm32duino` |Maple 003 |`1EAF:0003` |WinUSB |

View File

@@ -1,25 +1,18 @@
# EEPROM Driver Configuration :id=eeprom-driver-configuration
# EEPROM Driver Configuration
The EEPROM driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present.
Driver | Description
-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`EEPROM_DRIVER = vendor` (default) | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. STM32L0xx and STM32L1xx will use the onboard dedicated true EEPROM. Other chips will generally act as "transient" below.
`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below.
`EEPROM_DRIVER = spi` | Supports writing to SPI-based 25xx EEPROM chips. See the driver section below.
`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost.
Driver | Description
--------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`EEPROM_DRIVER = vendor` | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. Other chips will generally act as "transient" below.
`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below.
`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost.
## Vendor Driver Configuration :id=vendor-eeprom-driver-configuration
## Vendor Driver Configuration
#### STM32 L0/L1 Configuration :id=stm32l0l1-eeprom-driver-configuration
No configurable options are available.
!> Resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.
`config.h` override | Description | Default Value
------------------------------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------
`#define STM32_ONBOARD_EEPROM_SIZE` | The size of the EEPROM to use, in bytes. Erase times can be high, so it's configurable here, if not using the default value. | Minimum required to cover base _eeconfig_ data, or `1024` if VIA is enabled.
## I2C Driver Configuration :id=i2c-eeprom-driver-configuration
## I2C Driver Configuration
Currently QMK supports 24xx-series chips over I2C. As such, requires a working i2c_master driver configuration. You can override the driver configuration via your config.h:
@@ -40,28 +33,13 @@ Module | Equivalent `#define` | Source
-----------------|---------------------------------|------------------------------------------
CAT24C512 EEPROM | `#define EEPROM_I2C_CAT24C512` | <https://www.sparkfun.com/products/14764>
RM24C512C EEPROM | `#define EEPROM_I2C_RM24C512C` | <https://www.sparkfun.com/products/14764>
24LC64 EEPROM | `#define EEPROM_I2C_24LC64` | <https://www.microchip.com/wwwproducts/en/24LC64>
24LC128 EEPROM | `#define EEPROM_I2C_24LC128` | <https://www.microchip.com/wwwproducts/en/24LC128>
24LC256 EEPROM | `#define EEPROM_I2C_24LC256` | <https://www.sparkfun.com/products/525>
MB85RC256V FRAM | `#define EEPROM_I2C_MB85RC256V` | <https://www.adafruit.com/product/1895>
?> If you find that the EEPROM is not cooperating, ensure you've correctly shifted up your EEPROM address by 1. For example, the datasheet might state the address as `0b01010000` -- the correct value of `EXTERNAL_EEPROM_I2C_BASE_ADDRESS` needs to be `0b10100000`.
## SPI Driver Configuration :id=spi-eeprom-driver-configuration
Currently QMK supports 25xx-series chips over SPI. As such, requires a working spi_master driver configuration. You can override the driver configuration via your config.h:
`config.h` override | Description | Default Value
-----------------------------------------------|--------------------------------------------------------------------------------------|--------------
`#define EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN` | SPI Slave select pin in order to inform that the EEPROM is currently being addressed | _none_
`#define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR` | Clock divisor used to divide the peripheral clock to derive the SPI frequency | `64`
`#define EXTERNAL_EEPROM_BYTE_COUNT` | Total size of the EEPROM in bytes | 8192
`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32
`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2
!> There's no way to determine if there is an SPI EEPROM actually responding. Generally, this will result in reads of nothing but zero.
## Transient Driver configuration :id=transient-eeprom-driver-configuration
## Transient Driver configuration
The only configurable item for the transient EEPROM driver is its size:

View File

@@ -13,7 +13,7 @@ QMK (*Quantum Mechanical Keyboard*) es una comunidad open source que mantiene el
## Cómo conseguirlo
Si estás pensando en contribuir con un keymap, teclado, or característica a QMK, la manera más sencilla es hacer un [fork del repositorio en GitHub](https://github.com/qmk/qmk_firmware#fork-destination-box), y clonar tu repositorio localmente para hacer los cambios, subirlos, y abir un [Pull Request](https://github.com/qmk/qmk_firmware/pulls) desde tu fork.
Si estás pensando en contribuir con un keymap, teclado, or característica a QMK, la manera más sencilla es hacer un [fork del repositorio en Github](https://github.com/qmk/qmk_firmware#fork-destination-box), y clonar tu repositorio localmente para hacer los cambios, subirlos, y abir un [Pull Request](https://github.com/qmk/qmk_firmware/pulls) desde tu fork.
De cualquier manera, también puedes descargarlo directamente en formatos ([zip](https://github.com/qmk/qmk_firmware/zipball/master), [tar](https://github.com/qmk/qmk_firmware/tarball/master)), o clonarlo via git (`git@github.com:qmk/qmk_firmware.git`), o https (`https://github.com/qmk/qmk_firmware.git`).

View File

@@ -11,7 +11,7 @@
* [QMK CLI](es/cli.md)
* [Configuración de QMK CLI](es/cli_configuration.md)
* [Contribuyendo a QMK](es/contributing.md)
* [Cómo usar GitHub](es/getting_started_github.md)
* [Cómo usar Github](es/getting_started_github.md)
* [Obtener ayuda](es/getting_started_getting_help.md)
* [Cambios incompatibles](es/breaking_changes.md)
@@ -77,7 +77,7 @@
* [Macros](es/feature_macros.md)
* [Teclas del ratón](es/feature_mouse_keys.md)
* [Driver OLED](es/feature_oled_driver.md)
* [Teclas One Shot](es/one_shot_keys.md)
* [Teclas One Shot](es/feature_advanced_keycodes.md#one-shot-keys)
* [Dispositivo de apuntado](es/feature_pointing_device.md)
* [Ratón PS/2](es/feature_ps2_mouse.md)
* [Iluminación RGB](es/feature_rgblight.md)
@@ -98,7 +98,6 @@
* [Guía de flasheado de ISP](es/isp_flashing_guide.md)
* [Guía de depuración de ARM](es/arm_debugging.md)
* [Driver I2C](es/i2c_driver.md)
* [Driver SPI](es/spi_driver.md)
* [Controles GPIO](es/internals_gpio_control.md)
* [Conversión Proton C](es/proton_c_conversion.md)
@@ -109,7 +108,7 @@
* Otros temas
* [Usando Eclipse con QMK](es/other_eclipse.md)
* [Usando VSCode con QMK](es/other_vscode.md)
* [Soporte](es/getting_started_getting_help.md)
* [Soporte](es/support.md)
* [Cómo añadir traducciones](es/translating.md)
* QMK Internals (En progreso)

View File

@@ -0,0 +1,9 @@
# Llegar a ser un colaborador QMK
Un colaborador QMK es un maker o diseñador de teclados que tiene interés en ayudar a QMK a crecer y mantener sus teclado(s), y alentar a los usuarios y clientes a presentar herramientas, ideas, y keymaps. Siempre procuramos agregar más teclados y colaboradores, pero pedimos que cumplan los siguientes requisitos:
* **Tener un PCB disponible a la venta.** Desafortunadamente, hay demasiada variación y complicaciones con teclados cableados a mano.
* **Realizar el mantenimiento de tu teclado en QMK.** Este podría requirir un setup inicial para hacer que tu teclado funcione, pero también podría incluir adaptarse a cambios hecho al base de QMK que podrían descomponer o rendir código superfluo.
* **Aprobar e incorporar pull requests de keymaps para tu teclado.** Nos gusta alentar a los usuarios a contribuir sus keymaps para que otros los vean y los puedan usar para crear sus propios.
Si sientes que cumples los requisitos, ¡mándanos un email a hello@qmk.fm con una introducción y algunos enlaces para tu teclado!

View File

@@ -67,7 +67,7 @@ El archivo `config.h` es donde configuras el hardware y el conjunto de caracter
En la parte superior de `config.h` encontrarás ajustes relacionados con USB. Estos controlan la apariencia de tu teclado en el Sistema Operativo. Si no tienes una buena razón para cambiar debes dejar el `VENDOR_ID` como `0xFEED`. Para el `PRODUCT_ID` debes seleccionar un número que todavía no esté en uso.
Cambia las líneas de `MANUFACTURER` y `PRODUCT` para reflejar con precisión tu teclado.
Cambia las líneas de `MANUFACTURER`, `PRODUCT`, y `DESCRIPTION` para reflejar con precisión tu teclado.
```c
#define VENDOR_ID 0xFEED
@@ -75,6 +75,7 @@ Cambia las líneas de `MANUFACTURER` y `PRODUCT` para reflejar con precisión tu
#define DEVICE_VER 0x0001
#define MANUFACTURER Tú
#define PRODUCT mi_teclado_fantastico
#define DESCRIPTION Un teclado personalizado
```
?> Windows y macOS mostrarán el `MANUFACTURER` y `PRODUCT` en la lista de dispositivos USB. `lsusb` en Linux toma estos de la lista mantenida por el [Repositorio de ID USB](http://www.linux-usb.org/usb-ids.html) por defecto. `lsusb -v` mostrará los valores reportados por el dispositivo, y también están presentes en los registros del núcleo después de conectarlo.

View File

@@ -33,3 +33,4 @@ Soporte para hasta 2 controladores. Cada controlador implementa 2 matrices charl
## IS31FL3733
Soporte para hasta un solo controlador con espacio para expansión. Cada controlador puede controlar 192 LEDs individuales o 64 LEDs RGB. Para obtener más información sobre cómo configurar el controlador, consulta la página de [Matriz RGB](feature_rgb_matrix.md).

View File

@@ -6,7 +6,7 @@ Este documento procura instruir a los novatos en las mejores prácticas para ten
En este documento suponemos un par de cosas:
1. Tienes una cuenta de GitHub, y has hecho un [fork del repo qmk_firmware](getting_started_github.md) en tu cuenta.
1. Tienes una cuenta de Github, y has hecho un [fork del repo qmk_firmware](getting_started_github.md) en tu cuenta.
2. Has [configurado tu entorno de desarrollo](newbs_getting_started.md?id=environment-setup).

View File

@@ -4,7 +4,7 @@ El [Configurador QMK](https://config.qmk.fm) es un entorno gráfico online que g
?> **Por favor sigue estos pasos en orden.**
Ve el [Video tutorial](https://www.youtube.com/watch?v=-imgglzDMdY)
Ve el [Video tutorial](https://youtu.be/tx54jkRC9ZY)
El Configurador QMK functiona mejor con Chrome/Firefox.
@@ -21,7 +21,7 @@ Lo diré otra vez porque es importante
!> **ASEGÚRATE DE QUE SELECCIONAS LA VERSIÓN CORRECTA!**
Si se ha anunciado que tu teclado funciona con QMK pero no está en la lista, es probable que un desarrollador no se haya encargado de él aún o que todavía no hemos tenido la oportunidad de incluirlo. Abre un issue en [qmk_firmware](https://github.com/qmk/qmk_firmware/issues) solicitando soportar ese teclado un particular, si no hay un [Pull Request](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) activo para ello. Hay también teclados que funcionan con QMK que están en las cuentas de GitHub de sus manufacturantes. Acuérdate de comprobar esto también.
Si se ha anunciado que tu teclado funciona con QMK pero no está en la lista, es probable que un desarrollador no se haya encargado de él aún o que todavía no hemos tenido la oportunidad de incluirlo. Abre un issue en [qmk_firmware](https://github.com/qmk/qmk_firmware/issues) solicitando soportar ese teclado un particular, si no hay un [Pull Request](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) activo para ello. Hay también teclados que funcionan con QMK que están en las cuentas de github de sus manufacturantes. Acuérdate de comprobar esto también.
## Eligiendo el layout de tu teclado

View File

@@ -6,7 +6,7 @@ Recursos de Git:
* [Excelente tutorial general](https://www.codecademy.com/learn/learn-git)
* [Juego de Git para aprender usando ejemplos](https://learngitbranching.js.org/)
* [Recursos de Git para aprender más sobre GitHub](getting_started_github.md)
* [Recursos de Git para aprender más sobre Github](getting_started_github.md)
* [Recursos de Git dirigidos específicamente a QMK](contributing.md)

View File

@@ -41,9 +41,7 @@ Para plataformas compatibles, [QMK Toolbox](https://github.com/qmk/qmk_toolbox)
A veces, es útil imprimir mensajes de depuración desde tu [código personalizado](custom_quantum_functions.md). Hacerlo es bastante simple. Comienza incluyendo `print.h` al principio de tu fichero:
```c
#include "print.h"
```
#include <print.h>
Después de eso puedes utilzar algunas funciones print diferentes:

6
docs/faq.md Normal file
View File

@@ -0,0 +1,6 @@
# Frequently Asked Questions
* [General](faq_general.md)
* [Building or Compiling QMK](faq_build.md)
* [Debugging and Troubleshooting QMK](faq_debug.md)
* [Keymap](faq_keymap.md)

View File

@@ -13,29 +13,68 @@ An example of using `sudo`, when your controller is ATMega32u4:
or just:
$ sudo make <keyboard>:<keymap>:flash
$ sudo make <keyboard>:<keymap>:dfu
Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible.
### Linux `udev` Rules
On Linux, you'll need proper privileges to communicate with the bootloader device. You can either use `sudo` when flashing firmware (not recommended), or place [this file](https://github.com/qmk/qmk_firmware/tree/master/util/udev/50-qmk.rules) into `/etc/udev/rules.d/`.
Once added, run the following:
```
On Linux, you'll need proper privileges to access the MCU. You can either use
`sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`. Once added run the following:
```console
sudo udevadm control --reload-rules
sudo udevadm trigger
```
**Note:** With older versions of ModemManager (< 1.12), filtering only works when not in strict mode. The following commands can update that setting:
**/etc/udev/rules.d/50-atmel-dfu.rules:**
```
# Atmel ATMega32U4
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", MODE:="0666"
# Atmel USBKEY AT90USB1287
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", MODE:="0666"
# Atmel ATMega32U2
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff0", MODE:="0666"
```
**/etc/udev/rules.d/52-tmk-keyboard.rules:**
```
# tmk keyboard products https://github.com/tmk/tmk_keyboard
SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
```
**/etc/udev/rules.d/54-input-club-keyboard.rules:**
```
printf '[Service]\nExecStart=\nExecStart=/usr/sbin/ModemManager --filter-policy=default' | sudo tee /etc/systemd/system/ModemManager.service.d/policy.conf
# Input Club keyboard bootloader
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", MODE:="0666"
```
**/etc/udev/rules.d/55-caterina.rules:**
```
# ModemManager should ignore the following devices
ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"
```
**Note:** ModemManager filtering only works when not in strict mode, the following commands can update that settings:
```console
sudo sed -i 's/--filter-policy=strict/--filter-policy=default/' /lib/systemd/system/ModemManager.service
sudo systemctl daemon-reload
sudo systemctl restart ModemManager
```
**/etc/udev/rules.d/56-dfu-util.rules:**
```
# stm32duino
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", MODE:="0666"
# Generic stm32
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666"
```
**/etc/udev/rules.d/57-bootloadhid.rules:**
```
# bootloadHID
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", MODE:="0666"
```
### Serial device is not detected in bootloader mode on Linux
Make sure your kernel has appropriate support for your device. If your device uses USB ACM, such as
Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices may require `USB_SERIAL` and any of its sub options.
@@ -60,6 +99,56 @@ You can buy a really unique VID:PID here. I don't think you need this for person
- http://www.obdev.at/products/vusb/license.html
- http://www.mcselec.com/index.php?page=shop.product_details&flypage=shop.flypage&product_id=92&option=com_phpshop&Itemid=1
## BOOTLOADER_SIZE for AVR
Note that Teensy2.0++ bootloader size is 2048byte. Some Makefiles may have wrong comment.
```
# Boot Section Size in *bytes*
# Teensy halfKay 512
# Teensy++ halfKay 2048
# Atmel DFU loader 4096 (TMK Alt Controller)
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=2048
```
## `avr-gcc: internal compiler error: Abort trap: 6 (program cc1)` on MacOS
This is an issue with updating on brew, causing symlinks that avr-gcc depend on getting mangled.
The solution is to remove and reinstall all affected modules.
```
brew rm avr-gcc
brew rm avr-gcc@8
brew rm dfu-programmer
brew rm dfu-util
brew rm gcc-arm-none-eabi
brew rm arm-gcc-bin@8
brew rm avrdude
brew install avr-gcc@8
brew install dfu-programmer
brew install dfu-util
brew install arm-gcc-bin@8
brew install avrdude
brew link --force avr-gcc@8
brew link --force arm-gcc-bin@8
```
### `avr-gcc` and LUFA
If you updated your `avr-gcc` and you see errors involving LUFA, for example:
`lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h:380:5: error: 'const' attribute on function returning 'void'`
For now, you need to rollback `avr-gcc` to 8 in Homebrew.
```
brew uninstall --force avr-gcc
brew install avr-gcc@8
brew link --force avr-gcc@8
```
### I just flashed my keyboard and it does nothing/keypresses don't register - it's also ARM (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019)
Due to how EEPROM works on ARM based chips, saved settings may no longer be valid. This affects the default layers, and *may*, under certain circumstances we are still figuring out, make the keyboard unusable. Resetting the EEPROM will correct this.

View File

@@ -31,6 +31,20 @@ Check:
- try using 'print' function instead of debug print. See **common/print.h**.
- disconnect other devices with console function. See [Issue #97](https://github.com/tmk/tmk_keyboard/issues/97).
## Linux or UNIX Like System Requires Super User Privilege
Just use 'sudo' to execute *hid_listen* with privilege.
```
$ sudo hid_listen
```
Or add an *udev rule* for TMK devices with placing a file in rules directory. The directory may vary on each system.
File: /etc/udev/rules.d/52-tmk-keyboard.rules(in case of Ubuntu)
```
# tmk keyboard products https://github.com/tmk/tmk_keyboard
SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
```
***
# Miscellaneous
@@ -146,3 +160,10 @@ As of now root of its cause is not clear but some build options seem to be relat
https://github.com/tmk/tmk_keyboard/issues/266
https://geekhack.org/index.php?topic=41989.msg1967778#msg1967778
## FLIP Doesn't Work
### `AtLibUsbDfu.dll` Not Found
Remove current driver and reinstall one FLIP provides from DeviceManager.
http://imgur.com/a/bnwzy

View File

@@ -4,44 +4,6 @@
[QMK](https://github.com/qmk), short for Quantum Mechanical Keyboard, is a group of people building tools for custom keyboards. We started with the [QMK firmware](https://github.com/qmk/qmk_firmware), a heavily modified fork of [TMK](https://github.com/tmk/tmk_keyboard).
## I don't know where to start!
If this is the case, then you should start with our [Newbs Guide](newbs.md). There is a lot of great info there, and that should cover everything you need to get started.
If that's an issue, hop onto the [QMK Configurator](https://config.qmk.fm), as that will handle a majority of what you need there.
## How can I flash the firmware I built?
First, head to the [Compiling/Flashing FAQ Page](faq_build.md). There is a good deal of info there, and you'll find a bunch of solutions to common issues there.
## What if I have an issue that isn't covered here?
Okay, that's fine. Then please check the [open issues in our GitHub](https://github.com/qmk/qmk_firmware/issues) to see if somebody is experiencing the same thing (make sure it's not just similar, but actually the same).
If you can't find anything, then please open a [new issue](https://github.com/qmk/qmk_firmware/issues/new)!
## What if I found a bug?
Then please open an [issue](https://github.com/qmk/qmk_firmware/issues/new), and if you know how to fix it, open up a Pull Request on GitHub with the fix.
## But `git` and `GitHub` are intimidating!
Don't worry, we have some pretty nice [Guidelines](newbs_git_best_practices.md) on how to start using `git` and GitHub to make things easier to develop.
Additionally, you can find additional `git` and GitHub related links [here](newbs_learn_more_resources.md).
## I have a Keyboard that I want to add support for
Awesome! Open up a Pull Request for it. We'll review the code, and merge it!
### What if I want to do brand it with `QMK`?
That's amazing! We would love to assist you with that!
In fact, we have a [whole page](https://qmk.fm/powered/) dedicated to adding QMK Branding to your page and keyboard. This covers pretty much everything you need (knowledge and images) to officially support QMK.
If you have any questions about this, open an issue or head to [Discord](https://discord.gg/Uq7gcHh).
## What Differences Are There Between QMK and TMK?
TMK was originally designed and implemented by [Jun Wako](https://github.com/tmk). QMK started as [Jack Humbert](https://github.com/jackhumbert)'s fork of TMK for the Planck. After a while Jack's fork had diverged quite a bit from TMK, and in 2015 Jack decided to rename his fork to QMK.

View File

@@ -14,17 +14,6 @@ There are 3 standard keyboard layouts in use around the world- ANSI, ISO, and JI
<!-- Source for this image: http://www.keyboard-layout-editor.com/#/gists/bf431647d1001cff5eff20ae55621e9a -->
![Keyboard Layout Image](https://i.imgur.com/5wsh5wM.png)
## How Can I Make Custom Names For Complex Keycodes?
Sometimes, for readability's sake, it's useful to define custom names for some keycodes. People often define custom names using `#define`. For example:
```c
#define FN_CAPS LT(_FL, KC_CAPSLOCK)
#define ALT_TAB LALT(KC_TAB)
```
This will allow you to use `FN_CAPS` and `ALT_TAB` in your keymap, keeping it more readable.
## Some Of My Keys Are Swapped Or Not Working
QMK has two features, Bootmagic and Command, which allow you to change the behavior of your keyboard on the fly. This includes, but is not limited to, swapping Ctrl/Caps, disabling Gui, swapping Alt/Gui, swapping Backspace/Backslash, disabling all keys, and other behavioral modifications.

View File

@@ -1,44 +1,385 @@
# Modifier Keys :id=modifier-keys
# Advanced Keycodes
Your keymap can include keycodes that are more advanced than normal, for example keys that switch layers or send modifiers when held, but send regular keycodes when tapped. This page documents the functions that are available to you.
## Assigning Custom Names
People often define custom names using `#define`. For example:
```c
#define FN_CAPS LT(_FL, KC_CAPSLOCK)
#define ALT_TAB LALT(KC_TAB)
```
This will allow you to use `FN_CAPS` and `ALT_TAB` in your keymap, keeping it more readable.
## Caveats
Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Modifiers specified as part of a Layer Tap or Mod Tap's keycode will be ignored. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this.
Additionally, if at least one right-handed modifier is specified in a Mod Tap or Layer Tap, it will cause all modifiers specified to become right-handed, so it is not possible to mix and match the two.
# Switching and Toggling Layers
These functions allow you to activate layers in various ways. Note that layers are not generally independent layouts -- multiple layers can be activated at once, and it's typical for layers to use `KC_TRNS` to allow keypresses to pass through to lower layers. For a detailed explanation of layers, see [Keymap Overview](keymap.md#keymap-and-layers). When using momentary layer switching with MO(), LM(), TT(), or LT(), make sure to leave the key on the above layers transparent or it may not work as intended.
* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).)
* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated.
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15.
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](#one-shot-keys) for details and additional functionality.
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed).
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
# Working with Layers
Care must be taken when switching layers, it's possible to lock yourself into a layer with no way to deactivate that layer (without unplugging your keyboard.) We've created some guidelines to help users avoid the most common problems.
## Beginners
If you are just getting started with QMK you will want to keep everything simple. Follow these guidelines when setting up your layers:
* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number).
* Arrange your layers in a "tree" layout, with layer 0 as the root. Do not try to enter the same layer from more than one other layer.
* In a layer's keymap, only reference higher-numbered layers. Because layers are processed from the highest-numbered (topmost) active layer down, modifying the state of lower layers can be tricky and error-prone.
## Intermediate Users
Sometimes you need more than one base layer. For example, if you want to switch between QWERTY and Dvorak, switch between layouts for different countries, or switch your layout for different videogames. Your base layers should always be the lowest numbered layers. When you have multiple base layers you should always treat them as mutually exclusive. When one base layer is on the others are off.
## Advanced Users
Once you have a good feel for how layers work and what you can do, you can get more creative. The rules listed in the beginner section will help you be successful by avoiding some of the tricker details but they can be constraining, especially for ultra-compact keyboard users. Understanding how layers work will allow you to use them in more advanced ways.
Layers stack on top of each other in numerical order. When determining what a keypress does, QMK scans the layers from the top down, stopping when it reaches the first active layer that is not set to `KC_TRNS`. As a result if you activate a layer that is numerically lower than your current layer, and your current layer (or another layer that is active and higher than your target layer) has something other than `KC_TRNS`, that is the key that will be sent, not the key on the layer you just activated. This is the cause of most people's "why doesn't my layer get switched" problem.
Sometimes, you might want to switch between layers in a macro or as part of a tap dance routine. `layer_on` activates a layer, and `layer_off` deactivates it. More layer-related functions can be found in [action_layer.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/action_layer.h).
# Modifier Keys
These allow you to combine a modifier with a keycode. When pressed, the keydown event for the modifier, then `kc` will be sent. On release, the keyup event for `kc`, then the modifier will be sent.
|Key |Aliases |Description |
|----------|-------------------------------|------------------------------------------------------|
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|`LALT(kc)`|`A(kc)`, `LOPT(kc)` |Hold Left Alt and press `kc` |
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|`RALT(kc)`|`ROPT(kc)`, `ALGR(kc)` |Hold Right Alt and press `kc` |
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|`LSA(kc)` | |Hold Left Shift and Left Alt and press `kc` |
|`RSA(kc)` |`SAGR(kc)` |Hold Right Shift and Right Alt (AltGr) and press `kc` |
|`RCS(kc)` | |Hold Right Control and Right Shift and press `kc` |
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc` |
|Key |Aliases |Description |
|----------|-------------------------------|----------------------------------------------------|
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|`LALT(kc)`|`A(kc)` |Hold Left Alt and press `kc` |
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|`RALT(kc)`|`ALGR(kc)` |Hold Right Alt and press `kc` |
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc`|
You can also chain them, for example `LCTL(LALT(KC_DEL))` or `C(A(KC_DEL))` makes a key that sends Control+Alt+Delete with a single keypress.
You can also chain them, for example `LCTL(LALT(KC_DEL))` makes a key that sends Control+Alt+Delete with a single keypress.
# Legacy Content :id=legacy-content
# Mod-Tap
This page used to encompass a large set of features. We have moved many sections that used to be part of this page to their own pages. Everything below this point is simply a redirect so that people following old links on the web find what they're looking for.
The Mod-Tap key `MT(mod, kc)` acts like a modifier when held, and a regular keycode when tapped. In other words, you can have a key that sends Escape when you tap it, but functions as a Control or Shift key when you hold it down.
## Layers :id=switching-and-toggling-layers
The modifiers this keycode and `OSM()` accept are prefixed with `MOD_`, not `KC_`:
* [Layers](feature_layers.md)
|Modifier |Description |
|----------|----------------------------------------|
|`MOD_LCTL`|Left Control |
|`MOD_LSFT`|Left Shift |
|`MOD_LALT`|Left Alt |
|`MOD_LGUI`|Left GUI (Windows/Command/Meta key) |
|`MOD_RCTL`|Right Control |
|`MOD_RSFT`|Right Shift |
|`MOD_RALT`|Right Alt (AltGr) |
|`MOD_RGUI`|Right GUI (Windows/Command/Meta key) |
|`MOD_HYPR`|Hyper (Left Control, Shift, Alt and GUI)|
|`MOD_MEH` |Meh (Left Control, Shift, and Alt) |
## Mod-Tap :id=mod-tap
You can combine these by ORing them together like so:
* [Mod-Tap](mod_tap.md)
```c
MT(MOD_LCTL | MOD_LSFT, KC_ESC)
```
## One Shot Keys :id=one-shot-keys
This key would activate Left Control and Left Shift when held, and send Escape when tapped.
* [One Shot Keys](one_shot_keys.md)
For convenience, QMK includes some Mod-Tap shortcuts to make common combinations more compact in your keymap:
## Tap-Hold Configuration Options :id=tap-hold-configuration-options
|Key |Aliases |Description |
|------------|-----------------------------------------------------------------|-------------------------------------------------------|
|`LCTL_T(kc)`|`CTL_T(kc)` |Left Control when held, `kc` when tapped |
|`LSFT_T(kc)`|`SFT_T(kc)` |Left Shift when held, `kc` when tapped |
|`LALT_T(kc)`|`ALT_T(kc)` |Left Alt when held, `kc` when tapped |
|`LGUI_T(kc)`|`LCMD_T(kc)`, `LWIN_T(kc)`, `GUI_T(kc)`, `CMD_T(kc)`, `WIN_T(kc)`|Left GUI when held, `kc` when tapped |
|`RCTL_T(kc)`| |Right Control when held, `kc` when tapped |
|`RSFT_T(kc)`| |Right Shift when held, `kc` when tapped |
|`RALT_T(kc)`|`ALGR_T(kc)` |Right Alt when held, `kc` when tapped |
|`RGUI_T(kc)`|`RCMD_T(kc)`, `RWIN_T(kc)` |Right GUI when held, `kc` when tapped |
|`SGUI_T(kc)`|`SCMD_T(kc)`, `SWIN_T(kc)` |Left Shift and GUI when held, `kc` when tapped |
|`LCA_T(kc)` | |Left Control and Alt when held, `kc` when tapped |
|`LCAG_T(kc)`| |Left Control, Alt and GUI when held, `kc` when tapped |
|`RCAG_T(kc)`| |Right Control, Alt and GUI when held, `kc` when tapped |
|`C_S_T(kc)` | |Left Control and Shift when held, `kc` when tapped |
|`MEH_T(kc)` | |Left Control, Shift and Alt when held, `kc` when tapped|
|`HYPR_T(kc)`|`ALL_T(kc)` |Left Control, Shift, Alt and GUI when held, `kc` when tapped - more info [here](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)|
* [Tap-Hold Configuration Options](tap_hold.md)
## Caveats
Unfortunately, these keycodes cannot be used in Mod-Taps or Layer-Taps, since any modifiers specified in the keycode are ignored.
Additionally, you may run into issues when using Remote Desktop Connection on Windows. Because these codes send shift very fast, Remote Desktop may miss the codes.
To fix this, open Remote Desktop Connection, click on "Show Options", open the the "Local Resources" tab. In the keyboard section, change the drop down to "On this Computer". This will fix the issue, and allow the characters to work correctly.
# One Shot Keys
One shot keys are keys that remain active until the next key is pressed, and then are released. This allows you to type keyboard combinations without pressing more than one key at a time. These keys are usually called "Sticky keys" or "Dead keys".
For example, if you define a key as `OSM(MOD_LSFT)`, you can type a capital A character by first pressing and releasing shift, and then pressing and releasing A. Your computer will see the shift key being held the moment shift is pressed, and it will see the shift key being released immediately after A is released.
One shot keys also work as normal modifiers. If you hold down a one shot key and type other keys, your one shot will be released immediately after you let go of the key.
Additionally, hitting keys five times in a short period will lock that key. This applies for both One Shot Modifiers and One Shot Layers, and is controlled by the `ONESHOT_TAP_TOGGLE` define.
You can control the behavior of one shot keys by defining these in `config.h`:
```c
#define ONESHOT_TAP_TOGGLE 5 /* Tapping this number of times holds the key until tapped once again. */
#define ONESHOT_TIMEOUT 5000 /* Time (in ms) before the one shot key is released */
```
* `OSM(mod)` - Momentarily hold down *mod*. You must use the `MOD_*` keycodes as shown in [Mod Tap](#mod-tap), not the `KC_*` codes.
* `OSL(layer)` - momentary switch to *layer*.
Sometimes, you want to activate a one-shot key as part of a macro or tap dance routine.
For one shot layers, you need to call `set_oneshot_layer(LAYER, ONESHOT_START)` on key down, and `clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED)` on key up. If you want to cancel the oneshot, call `reset_oneshot_layer()`.
For one shot mods, you need to call `set_oneshot_mods(MOD)` to set it, or `clear_oneshot_mods()` to cancel it.
!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tap, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop.
## Callbacks
When you'd like to perform custom logic when pressing a one shot key, there are several callbacks you can choose to implement. You could indicate changes in one shot keys by flashing an LED or making a sound, for example.
There is a callback for `OSM(mod)`. It is called whenever the state of any one shot modifier key is changed: when it toggles on, but also when it is toggled off. You can use it like this:
```c
void oneshot_mods_changed_user(uint8_t mods) {
if (mods & MOD_MASK_SHIFT) {
println("Oneshot mods SHIFT");
}
if (mods & MOD_MASK_CTRL) {
println("Oneshot mods CTRL");
}
if (mods & MOD_MASK_ALT) {
println("Oneshot mods ALT");
}
if (mods & MOD_MASK_GUI) {
println("Oneshot mods GUI");
}
if (!mods) {
println("Oneshot mods off");
}
}
```
The `mods` argument contains the active mods after the change, so it reflects the current state.
When you use One Shot Tap Toggle (by adding `#define ONESHOT_TAP_TOGGLE 2` in your `config.h` file), you may lock a modifier key by pressing it the specified amount of times. There's a callback for that, too:
```c
void oneshot_locked_mods_changed_user(uint8_t mods) {
if (mods & MOD_MASK_SHIFT) {
println("Oneshot locked mods SHIFT");
}
if (mods & MOD_MASK_CTRL) {
println("Oneshot locked mods CTRL");
}
if (mods & MOD_MASK_ALT) {
println("Oneshot locked mods ALT");
}
if (mods & MOD_MASK_GUI) {
println("Oneshot locked mods GUI");
}
if (!mods) {
println("Oneshot locked mods off");
}
}
```
Last, there is also a callback for the `OSL(layer)` one shot key:
```c
void oneshot_layer_changed_user(uint8_t layer) {
if (layer == 1) {
println("Oneshot layer 1 on");
}
if (!layer) {
println("Oneshot layer off");
}
}
```
If any one shot layer is switched off, `layer` will be zero. When you're looking to do something on any layer change instead of one shot layer changes, `layer_state_set_user` is a better callback to use.
If you are making your own keyboard, there are also `_kb` equivalent functions:
```c
void oneshot_locked_mods_changed_kb(uint8_t mods);
void oneshot_mods_changed_kb(uint8_t mods);
void oneshot_layer_changed_kb(uint8_t layer);
```
As with any callback, be sure to call the `_user` variant to allow for further customizability.
# Tap-Hold Configuration Options
While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonal defaults, but that may still cause issues for some people.
These options let you modify the behavior of the Tap-Hold keys.
## Permissive Hold
As of [PR#1359](https://github.com/qmk/qmk_firmware/pull/1359/), there is a new `config.h` option:
```c
#define PERMISSIVE_HOLD
```
This makes tap and hold keys (like Mod Tap) work better for fast typist, or for high `TAPPING_TERM` settings.
If you press a Mod Tap key, tap another key (press and release) and then release the Mod Tap key, all within the tapping term, it will output the "tapping" function for both keys.
For Instance:
- `SFT_T(KC_A)` Down
- `KC_X` Down
- `KC_X` Up
- `SFT_T(KC_A)` Up
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms) this will be registered as `ax` by the firmware and host system. With permissive hold enabled, this modifies how this is handled by considering the Mod Tap keys as a Mod if another key is tapped, and would registered as `X` (`SHIFT`+`x`).
?> If you have `Ignore Mod Tap Interrupt` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`.
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define PERMISSIVE_HOLD_PER_KEY
```
You can then add the following function to your keymap:
```c
bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case SFT_T(KC_A):
return true;
default:
return false;
}
}
```
## Ignore Mod Tap Interrupt
To enable this setting, add this to your `config.h`:
```c
#define IGNORE_MOD_TAP_INTERRUPT
```
Similar to Permissive Hold, this alters how the firmware processes input for fast typist. If you press a Mod Tap key, press another key, release the Mod Tap key, and then release the normal key, it would normally output the "tapping" function for both keys. This may not be desirable for rolling combo keys.
Setting `Ignore Mod Tap Interrupt` requires holding both keys for the `TAPPING_TERM` to trigger the hold function (the mod).
For Instance:
- `SFT_T(KC_A)` Down
- `KC_X` Down
- `SFT_T(KC_A)` Up
- `KC_X` Up
Normally, this would send `X` (`SHIFT`+`x`). With `Ignore Mod Tap Interrupt` enabled, holding both keys are required for the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold on both will still output `X` (`SHIFT`+`x`).
?> __Note__: This only concerns modifiers and not layer switching keys.
?> If you have `Permissive Hold` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`.
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
```
You can then add the following function to your keymap:
```c
bool get_ignore_mod_tap_interrupt(uint16_t keycode) {
switch (keycode) {
case SFT_T(KC_SPC):
return true;
default:
return false;
}
}
```
## Tapping Force Hold
To enable `tapping force hold`, add the following to your `config.h`:
```c
#define TAPPING_FORCE_HOLD
```
When the user holds a key after tap, this repeats the tapped key rather to hold a modifier key. This allows to use auto repeat for the tapped key.
Example:
- SFT_T(KC_A) Down
- SFT_T(KC_A) Up
- SFT_T(KC_A) Down
- wait more than tapping term...
- SFT_T(KC_A) Up
With default settings, `a` will be sent on the first release, then `a` will be sent on the second press allowing the computer to trigger its auto repeat function.
With `TAPPING_FORCE_HOLD`, the second press will be interpreted as a Shift, allowing to use it as a modifier shortly after having used it as a tap.
!> `TAPPING_FORCE_HOLD` will break anything that uses tapping toggles (Such as the `TT` layer keycode, and the One Shot Tapping Toggle).
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define TAPPING_FORCE_HOLD_PER_KEY
```
You can then add the following function to your keymap:
```c
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LT(1, KC_BSPC):
return true;
default:
return false;
}
}
```
## Retro Tapping
To enable `retro tapping`, add the following to your `config.h`:
```c
#define RETRO_TAPPING
```
Holding and releasing a dual function key without pressing another key will result in nothing happening. With retro tapping enabled, releasing the key without pressing another will send the original keycode even if it is outside the tapping term.
For instance, holding and releasing `LT(2, KC_SPACE)` without hitting another key will result in nothing happening. With this enabled, it will send `KC_SPACE` instead.

View File

@@ -15,31 +15,25 @@ problem.
When you tap a key, it stays depressed for a short period of time before it is
then released. This depressed time is a different length for everyone. Auto Shift
defines a constant `AUTO_SHIFT_TIMEOUT` which is typically set to twice your
normal pressed state time. When you press a key, a timer starts, and if you
have not released the key after the `AUTO_SHIFT_TIMEOUT` period, then a shifted
version of the key is emitted. If the time is less than the `AUTO_SHIFT_TIMEOUT`
time, or you press another key, then the normal state is emitted.
If `AUTO_SHIFT_REPEAT` is defined, there is keyrepeat support. Holding the key
down will repeat the shifted key, though this can be disabled with
`AUTO_SHIFT_NO_AUTO_REPEAT`. If you want to repeat the normal key, then tap it
once then immediately (within `TAPPING_TERM`) hold it down again (this works
with the shifted value as well if auto-repeat is disabled).
normal pressed state time. When you press a key, a timer starts and then stops
when you release the key. If the time depressed is greater than or equal to the
`AUTO_SHIFT_TIMEOUT`, then a shifted version of the key is emitted. If the time
is less than the `AUTO_SHIFT_TIMEOUT` time, then the normal state is emitted.
## Are There Limitations to Auto Shift?
Yes, unfortunately.
You will have characters that are shifted when you did not intend on shifting, and
other characters you wanted shifted, but were not. This simply comes down to
practice. As we get in a hurry, we think we have hit the key long enough for a
shifted version, but we did not. On the other hand, we may think we are tapping
the keys, but really we have held it for a little longer than anticipated.
Additionally, with keyrepeat the desired shift state can get mixed up. It will
always 'belong' to the last key pressed. For example, keyrepeating a capital
and then tapping something lowercase (whether or not it's an Auto Shift key)
will result in the capital's *key* still being held, but shift not.
1. Key repeat will cease to work. For example, before if you wanted 20 'a'
characters, you could press and hold the 'a' key for a second or two. This no
longer works with Auto Shift because it is timing your depressed time instead
of emitting a depressed key state to your operating system.
2. You will have characters that are shifted when you did not intend on shifting, and
other characters you wanted shifted, but were not. This simply comes down to
practice. As we get in a hurry, we think we have hit the key long enough
for a shifted version, but we did not. On the other hand, we may think we are
tapping the keys, but really we have held it for a little longer than
anticipated.
## How Do I Enable Auto Shift?
@@ -109,14 +103,6 @@ Do not Auto Shift numeric keys, zero through nine.
Do not Auto Shift alpha characters, which include A through Z.
### AUTO_SHIFT_REPEAT (simple define)
Enables keyrepeat.
### AUTO_SHIFT_NO_AUTO_REPEAT (simple define)
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
## Using Auto Shift Setup
This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
@@ -153,7 +139,7 @@ completely normal and with no intention of shifted keys.
`KC_ASRP`. The keyboard will type by itself the value of your
`AUTO_SHIFT_TIMEOUT`.
7. Update `AUTO_SHIFT_TIMEOUT` in your `config.h` with the value reported.
8. Add `AUTO_SHIFT_NO_SETUP` to your `config.h`.
8. Remove `AUTO_SHIFT_SETUP` from your `config.h`.
9. Remove the key bindings `KC_ASDN`, `KC_ASUP` and `KC_ASRP`.
10. Compile and upload your new firmware.

View File

@@ -1,4 +1,4 @@
# Backlighting :id=backlighting
# 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.
@@ -6,107 +6,103 @@ QMK is able to control the brightness of these LEDs by switching them on and off
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.
## Feature Configuration
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:
```makefile
BACKLIGHT_ENABLE = yes
```
## Keycodes :id=keycodes
## Keycodes
Once enabled the following keycodes below can be used to change the backlight level.
Once enabled, the following keycodes below can be used to change the backlight level.
|Key |Description |
|---------|------------------------------------------|
|`BL_TOGG`|Turn the backlight on or off |
|`BL_STEP`|Cycle through backlight levels |
|`BL_ON` |Set the backlight to max brightness |
|`BL_OFF` |Turn the backlight off |
|`BL_INC` |Increase the backlight level |
|`BL_DEC` |Decrease the backlight level |
|`BL_BRTG`|Toggle backlight breathing |
|Key |Description |
|---------|-----------------------------------|
|`BL_TOGG`|Turn the backlight on or off |
|`BL_STEP`|Cycle through backlight levels |
|`BL_ON` |Set the backlight to max brightness|
|`BL_OFF` |Turn the backlight off |
|`BL_INC` |Increase the backlight level |
|`BL_DEC` |Decrease the backlight level |
|`BL_BRTG`|Toggle backlight breathing |
## Backlight Functions
## Functions :id=functions
|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 |
These functions can be used to change the backlighting in custom code:
### Backlight Breathing Functions
|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|
|Function |Description |
|----------|---------------------------------------------------|
|`breathing_toggle()` |Turn the backlight breathing on or off |
|`breathing_enable()` |Turns on backlight breathing |
|`breathing_disable()` |Turns off backlight breathing |
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
## Driver Configuration
To select which driver to use, configure your `rules.mk` with the following:
```makefile
BACKLIGHT_DRIVER = software
BACKLIGHT_DRIVER = software # Valid driver values are 'pwm,software,no'
```
Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help on individual drivers.
See below for help on individual drivers.
To configure the backlighting, `#define` these in your `config.h`:
## Common Driver Configuration
| Define | Default | Description |
|------------------------|---------------|-------------------------------------------------------------------------------------------------------------------|
| `BACKLIGHT_PIN` | *Not defined* | The pin that controls the LED(s) |
| `BACKLIGHT_LEVELS` | `3` | The number of brightness levels (maximum 31 excluding off) |
| `BACKLIGHT_CAPS_LOCK` | *Not defined* | Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
| `BACKLIGHT_BREATHING` | *Not defined* | Enable backlight breathing, if supported |
| `BREATHING_PERIOD` | `6` | The length of one backlight "breath" in seconds |
| `BACKLIGHT_ON_STATE` | `1` | The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
| `BACKLIGHT_LIMIT_VAL ` | `255` | The maximum duty cycle of the backlight -- `255` allows for full brightness, any lower will decrease the maximum. |
To change the behavior of 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`.
|Define |Default |Description |
|---------------------|-------------|--------------------------------------------------------------------------------------|
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|`BACKLIGHT_ON_STATE` |`0` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
### Backlight On State :id=backlight-on-state
### Backlight 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.
### AVR Driver :id=avr-driver
The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
## AVR driver
On AVR boards, the default driver currently sniffs the configuration to pick the best scenario. The driver is configured by default, however the equivalent setting within rules.mk would be:
```makefile
BACKLIGHT_DRIVER = pwm
```
#### Caveats :id=avr-caveats
### Caveats
On AVR boards, QMK automatically decides which driver to use according to the following table:
Hardware PWM is supported according to the following table:
|Backlight Pin|AT90USB64/128|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 | | |
|`C4` |Timer 3 | | | | |
|`C5` |Timer 3 | |Timer 1 | | |
|`C6` |Timer 3 |Timer 3 |Timer 1 | | |
|`D4` | | | |Timer 1 | |
|`D5` | | | |Timer 1 | |
|Backlight Pin|AT90USB64/128|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328P|
|-------------|-------------|-------------|-------------|---------|----------|
|`B1` | | | | |Timer 1 |
|`B2` | | | | |Timer 1 |
|`B5` |Timer 1 |Timer 1 | | | |
|`B6` |Timer 1 |Timer 1 | | | |
|`B7` |Timer 1 |Timer 1 |Timer 1 | | |
|`C4` |Timer 3 | | | | |
|`C5` |Timer 3 | |Timer 1 | | |
|`C6` |Timer 3 |Timer 3 |Timer 1 | | |
|`D4` | | | |Timer 1 | |
|`D5` | | | |Timer 1 | |
All other pins will use timer-assisted software PWM:
All other pins will use software PWM. If the [Audio](feature_audio.md) feature is disabled or only using one timer, the backlight PWM can be triggered by a hardware timer:
|Audio Pin|Audio Timer|Software PWM Timer|
|---------|-----------|------------------|
@@ -117,9 +113,44 @@ All other pins will use timer-assisted software PWM:
|`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.
When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but 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
### AVR Configuration
To change the behavior of the backlighting, `#define` these in your `config.h`:
|Define |Default |Description |
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|`BACKLIGHT_PINS` |*Not defined*|experimental: see below for more information |
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|`BACKLIGHT_ON_STATE` |`1` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
### Backlight 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.
### Multiple backlight pins
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an hardware PWM pin).
In software PWM, it is possible to define multiple backlight pins. All those pins 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 (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped LCTRL 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.
To activate multiple backlight pins, you need to add something like this to your user `config.h`:
```c
#define BACKLIGHT_LED_COUNT 2
#undef BACKLIGHT_PIN
#define BACKLIGHT_PINS { F5, B2 }
```
### 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.
@@ -128,7 +159,7 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
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
### Timer Assisted PWM 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.
@@ -137,82 +168,81 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
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:
## ARM Driver
While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The driver is configured by default, however the equivalent setting within rules.mk would be:
```makefile
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
### Caveats
Currently only hardware PWM is supported, not timer assisted, and does not provide automatic configuration.
### Software PWM Driver :id=software-pwm-driver
?> Backlight support for STMF072 has had limited testing, YMMV. If unsure, set `BACKLIGHT_ENABLE = no` in your rules.mk.
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`:
### ARM Configuration
To change the behavior of the backlighting, `#define` these in your `config.h`:
|Define |Default |Description |
|------------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use, see ST datasheets for pin to PWM timer mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|`BACKLIGHT_PWM_CHANNEL` |`3` |The PWM channel to use, see ST datasheets for pin to PWM channel mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use, see ST datasheets for pin AF mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
## Software PWM Driver
Emulation of PWM 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:
```makefile
BACKLIGHT_DRIVER = software
```
#### Multiple Backlight Pins :id=multiple-backlight-pins
### Software PWM Configuration
To change the behavior of the backlighting, `#define` these in your `config.h`:
|Define |Default |Description |
|-----------------|-------------|-------------------------------------------------------------------------------------------------------------|
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|`BACKLIGHT_PINS` |*Not defined*|experimental: see below for more information |
### Multiple backlight pins
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an 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.
In software PWM, it is possible to define multiple backlight pins. All those pins 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 (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped LCTRL 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.
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 activate multiple backlight pins, you need to add something like this to your user `config.h`:
```c
#undef BACKLIGHT_PIN
#define BACKLIGHT_PINS { F5, B2 }
```
### Custom Driver :id=custom-driver
## 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`:
To enable, add this to your rules.mk:
```makefile
BACKLIGHT_DRIVER = custom
```
Then implement any of these hooks:
When implementing the custom driver API, the provided keyboard hooks are as follows:
```c
void backlight_init_ports(void) {
// Optional - runs on startup
// Usually you want to configure pins here
// Optional - Run on startup
// - usually you want to configure pins here
}
void backlight_set(uint8_t level) {
// Optional - runs on level change
// Usually you want to respond to the new value
// Optional - Run on level change
// - usually you want to respond to the new value
}
void backlight_task(void) {
// Optional - runs periodically
// Note that this is called in the main keyboard loop,
// so long running actions here can cause performance issues
// Optional - Run periodically
// - long running actions here can cause performance issues
}
```
## Example Schematic
In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)

View File

@@ -2,10 +2,11 @@
## Bluetooth Known Supported Hardware
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules and the Bluefruit EZ-Key, the latter of which is not produced anymore. 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|
|----------------------------------------------------------------|----------------------------|----------------|---------------------------|--------------|
|[Adafruit EZ-Key HID](https://www.adafruit.com/product/1535) |Bluetooth Classic | UART |`BLUETOOTH = AdafruitEZKey` | |
|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic | UART |`BLUETOOTH = RN42` | RN-42 |
|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy | SPI |`BLUETOOTH = AdafruitBLE` | nRF51822 |
@@ -23,15 +24,16 @@ Currently The only bluetooth chipset supported by QMK is the Adafruit Bluefruit
A Bluefruit UART friend can be converted to an SPI friend, however this [requires](https://github.com/qmk/qmk_firmware/issues/2274) some reflashing and soldering directly to the MDBT40 chip.
## Adafruit EZ-Key hid
This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
<!-- FIXME: Document bluetooth support more completely. -->
## Bluetooth Rules.mk Options
The currently supported Bluetooth chipsets do not support [N-Key Rollover (NKRO)](reference_glossary.md#n-key-rollover-nkro), so `rules.mk` must contain `NKRO_ENABLE = no`.
Use only one of these to enable Bluetooth:
Use only one of these
* BLUETOOTH_ENABLE = yes (Legacy Option)
* BLUETOOTH = RN42
* BLUETOOTH = AdafruitEZKey
* BLUETOOTH = AdafruitBLE
## Bluetooth Keycodes

View File

@@ -54,7 +54,7 @@ Hold down the Bootmagic key (Space by default) and the desired hotkey while plug
|`6` |Make layer 6 the default layer |
|`7` |Make layer 7 the default layer |
## Keycodes :id=keycodes
## Keycodes
|Key |Aliases |Description |
|----------------------------------|---------|--------------------------------------------------------------------------|
@@ -121,9 +121,9 @@ If you would like to change the hotkey assignments for Bootmagic, `#define` thes
|`BOOTMAGIC_KEY_DEFAULT_LAYER_6` |`KC_6` |Make layer 6 the default layer |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_7` |`KC_7` |Make layer 7 the default layer |
# Bootmagic Lite :id=bootmagic-lite
# Bootmagic Lite
In addition to the full blown Bootmagic feature, is the Bootmagic Lite feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button but you need a way to jump into the bootloader, and don't want to deal with the headache that Bootmagic can cause.
In addition to the full blown Bootmagic feature, is the Bootmagic Lite feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button but you need a way to jump into the bootloader, and don't want to deal with the headache that Bootmagic can cause.
To enable this version of Bootmagic, you need to enable it in your `rules.mk` with:
@@ -131,7 +131,7 @@ To enable this version of Bootmagic, you need to enable it in your `rules.mk` wi
BOOTMAGIC_ENABLE = lite
```
Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file:
Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file:
```c
#define BOOTMAGIC_LITE_ROW 0
@@ -144,20 +144,9 @@ And to trigger the bootloader, you hold this key down when plugging the keyboard
!> Using bootmagic lite will **always reset** the EEPROM, so you will lose any settings that have been saved.
## Split Keyboards
When handedness is predetermined via an option like `SPLIT_HAND_PIN`, you might need to configure a different key between halves. This To do so, add these entries to your `config.h` file:
```c
#define BOOTMAGIC_LITE_ROW_RIGHT 4
#define BOOTMAGIC_LITE_COLUMN_RIGHT 1
```
By default, these values are not set.
## Advanced Bootmagic Lite
The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed.
The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed.
To replace the function, all you need to do is add something like this to your code:
@@ -174,4 +163,4 @@ void bootmagic_lite(void) {
}
```
You can additional feature here. For instance, resetting the eeprom or requiring additional keys to be pressed to trigger bootmagic. Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware.
You can additional feature here. For instance, resetting the eeprom or requiring additional keys to be pressed to trigger bootmagic. Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware.

View File

@@ -55,7 +55,7 @@ combo_t key_combos[COMBO_COUNT] = {
[XV_PASTE] = COMBO_ACTION(paste_combo),
};
void process_combo_event(uint16_t combo_index, bool pressed) {
void process_combo_event(uint8_t combo_index, bool pressed) {
switch(combo_index) {
case ZC_COPY:
if (pressed) {

View File

@@ -1,150 +1,42 @@
# Contact bounce / contact chatter
Mechanical switches often don't have a clean single transition between pressed and unpressed states.
In an ideal world, when you press a switch, you would expect the digital pin to see something like this:
(X axis showing time
```
voltage +----------------------
^ |
| |
| ------------------+
----> time
```
However in the real world you will actually see contact bounce, which will look like multiple 1->0 and 0->1 transitions,
until the value finally settles.
```
+-+ +--+ +-------------
| | | | |
| | | | |
+-----------------+ +-+ +-+
```
The time it takes for the switch to settle might vary with switch type, age, and even pressing technique.
If the device chooses not to mitigate contact bounce, then often actions that happen when the switch is pressed are repeated
multiple times.
There are many ways to handle contact bounce ("Debouncing"). Some include employing additional hardware, for example an RC filter,
while there are various ways to do debouncing in software too, often called debounce algorithms. This page discusses software
debouncing methods available in QMK.
While technically not considered contact bounce/contact chatter, some switch technologies are susceptible to noise, meaning,
while the key is not changing state, sometimes short random 0->1 or 1->0 transitions might be read by the digital circuit, for example:
```
+-+
| |
| |
+-----------------+ +--------------------
```
Many debounce methods (but not all) will also make the device resistant to noise. If you are working with a technology that is
susceptible to noise, you must choose a debounce method that will also mitigate noise for you.
## Types of debounce algorithms
1) Unit of time: Timestamp (milliseconds) vs Cycles (scans)
* Debounce algorithms often have a 'debounce time' parameter, that specifies the maximum settling time of the switch contacts.
This time might be measured in various units:
* Cycles-based debouncing waits n cycles (scans), decreasing count by one each matrix_scan
* Timestamp-based debouncing stores the millisecond timestamp a change occurred, and does substraction to figure out time elapsed.
* Timestamp-based debouncing is usually superior, especially in the case of noise-resistant devices because settling times of physical
switches is specified in units of time, and should not depend on the matrix scan-rate of the keyboard.
* Cycles-based debouncing is sometimes considered inferior, because the settling time that it is able to compensate for depends on the
performance of the matrix scanning code. If you use cycles-based debouncing, and you significantly improve the performance of your scanning
code, you might end up with less effective debouncing. A situation in which cycles-based debouncing might be preferable is when
noise is present, and the scanning algorithm is slow, or variable speed. Even if your debounce algorithm is fundamentally noise-resistant,
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.
2) Symmetric vs Asymmetric
* Symmetric - apply the same debouncing algorithm, to both key-up and key-down events.
* 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
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
* 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
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```
* Per-key - one timer per key
* Recommended naming convention: ```*_pk```
* Per-row - one timer per row
* 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
# Debounce algorithm
QMK supports multiple debounce algorithms through its debounce API.
The logic for which debounce method called is below. It checks various defines that you have set in ```rules.mk```
The logic for which debounce method called is below. It checks various defines that you have set in rules.mk
```
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
DEBOUNCE_TYPE?= sym_defer_g
DEBOUNCE_TYPE?= sym_g
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
endif
```
### Debounce selection
# Debounce selection
| DEBOUNCE_TYPE | Description | What else is needed |
| ------------- | --------------------------------------------------- | ----------------------------- |
| Not defined | Use the default algorithm, currently sym_defer_g | Nothing |
| Not defined | Use the default algorithm, currently sym_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 |
| anything_else | Use another algorithm from quantum/debounce/* | Nothing |
**Regarding split keyboards**:
The debounce code is compatible with split keyboards.
### Selecting an included debouncing method
Keyboards may select one of the already implemented debounce methods, by adding to ```rules.mk``` the following line:
```
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_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.
### A couple algorithms that could be implemented in the future:
* ```sym_defer_pr```
* ```sym_eager_g```
* ```asym_eager_defer_pk```
### 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```
# Use your own debouncing code
* Set ```DEBOUNCE_TYPE = custom```.
* Add ```SRC += debounce.c```
* Add your own ```debounce.c```. Look at current implementations in ```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```
### Old names
The following old names for existing algorithms will continue to be supported, however it is recommended to use the new names instead.
# Changing between included debouncing methods
You can either use your own code, by including your own debounce.c, or switch to another included one.
Included debounce methods are:
* 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.
* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
* sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occured, all input changes are pushed.
* sym_g - old name for sym_defer_g
* eager_pk - old name for sym_eager_pk
* sym_pk - old name for sym_defer_pk
* eager_pr - old name for sym_eager_pr

View File

@@ -7,17 +7,9 @@ DIP switches are supported by adding this to your `rules.mk`:
and this to your `config.h`:
```c
// Connects each switch in the dip switch to the GPIO pin of the MCU
#define DIP_SWITCH_PINS { B14, A15, A10, B9 }
```
or
```c
// Connect each switch in the DIP switch to an unused intersections in the key matrix.
#define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs
```
## Callbacks
The callback functions can be inserted into your `<keyboard>.c`:
@@ -95,10 +87,4 @@ void dip_switch_update_mask_user(uint32_t state) {
## Hardware
### Connects each switch in the dip switch to the GPIO pin of the MCU
One side of the DIP switch should be wired directly to the pin on the MCU, and the other side to ground. It should not matter which side is connected to which, as it should be functionally the same.
### Connect each switch in the DIP switch to an unused intersections in the key matrix.
As with the keyswitch, a diode and DIP switch connect the ROW line to the COL line.

View File

@@ -18,11 +18,11 @@ That should be everything necessary.
To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`.
To finish the recording, press the `DYN_REC_STOP` layer button. You can also press `DYN_REC_START1` or `DYN_REC_START2` again to stop the recording.
To finish the recording, press the `DYN_REC_STOP` layer button.
To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`.
It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completely by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file.
It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completly by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file.
?> For the details about the internals of the dynamic macros, please read the comments in the `process_dynamic_macro.h` and `process_dynamic_macro.c` files.

View File

@@ -26,26 +26,19 @@ If your encoder's clockwise directions are incorrect, you can swap the A & B pad
#define ENCODER_DIRECTION_FLIP
```
Additionally, the resolution, which defines how many pulses the encoder registers between each detent, can be defined with:
Additionally, the resolution can be specified in the same file (the default & suggested is 4):
```c
#define ENCODER_RESOLUTION 4
```
It can also be defined per-encoder, by instead defining:
```c
#define ENCODER_RESOLUTIONS { 4, 2 }
```
## Split Keyboards
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout for the right half like this:
```c
#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a }
#define ENCODERS_PAD_B_RIGHT { encoder1b, encoder2b }
#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 }
```
## Callbacks
@@ -68,7 +61,7 @@ void encoder_update_user(uint8_t index, bool clockwise) {
} else {
tap_code(KC_PGUP);
}
} else if (index == 1) { /* Second encoder */
} else if (index == 1) { /* Second encoder */
if (clockwise) {
tap_code(KC_DOWN);
} else {

View File

@@ -42,21 +42,14 @@ First you will need a build a circuit to drive the solenoid through a mosfet as
[Wiring diagram provided by Adafruit](https://playground.arduino.cc/uploads/Learning/solenoid_driver.pdf)
| Settings | Default | Description |
|----------------------------|----------------------|-------------------------------------------------------|
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
|`SOLENOID_DWELL_STEP_SIZE` | `1` ms |The step size to use when `HPT_DWL*` keycodes are sent |
|`SOLENOID_DEFAULT_BUZZ` | `0` (disabled) |On HPT_RST buzz is set "on" if this is "1" |
|`SOLENOID_BUZZ_ACTUATED` | `SOLENOID_MIN_DWELL` |Actuated-time when the solenoid is in buzz mode |
|`SOLENOID_BUZZ_NONACTUATED` | `SOLENOID_MIN_DWELL` |Non-Actuated-time when the solenoid is in buzz mode |
| Settings | Default | Description |
|--------------------------|---------------|-------------------------------------------------------|
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
* If solenoid buzz is off, then dwell time is how long the "plunger" stays activated. The dwell time changes how the solenoid sounds.
* If solenoid buzz is on, then dwell time sets the length of the buzz, while `SOLENOID_BUZZ_ACTUATED` and `SOLENOID_BUZZ_NONACTUATED` set the (non-)actuation times withing the buzz period.
* With the current implementation, for any of the above time settings, the precision of these settings may be affected by how fast the keyboard is able to scan the matrix.
Therefore, if the keyboards scanning routine is slow, it may be preferable to set `SOLENOID_DWELL_STEP_SIZE` to a value slightly smaller than the time it takes to scan the keyboard.
?> Dwell time is how long the "plunger" stays activated. The dwell time changes how the solenoid sounds.
Beware that some pins may be powered during bootloader (ie. A13 on the STM32F303 chip) and will result in the solenoid kept in the on state through the whole flashing process. This may overheat and damage the solenoid. If you find that the pin the solenoid is connected to is triggering the solenoid during bootloader/DFU, select another pin.

View File

@@ -1,6 +1,6 @@
# HD44780 LCD Displays
This is an integration of Peter Fleury's LCD library. This page will explain the basics. [For in depth documentation visit his page.](http://www.peterfleury.epizy.com/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
This is an integration of Peter Fleury's LCD library. This page will explain the basics. [For in depth documentation visit his page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
You can enable support for HD44780 Displays by setting the `HD44780_ENABLE` flag in your keyboards `rules.mk` to yes.
@@ -50,8 +50,8 @@ LCD_DISP_ON_CURSOR_BLINK : display on, cursor on flashing
````
This is best done in your keyboards `matrix_init_kb` or your keymaps `matrix_init_user`.
It is advised to clear the display before use.
To do so call `lcd_clrscr()`.
To do so call `lcd_clrsrc()`.
To now print something to your Display you first call `lcd_gotoxy(column, line)`. To go to the start of the first line you would call `lcd_gotoxy(0, 0)` and then print a string with `lcd_puts("example string")`.
There are more methods available to control the display. [For in depth documentation please visit the linked page.](http://www.peterfleury.epizy.com/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
There are more methods available to control the display. [For in depth documentation please visit the linked page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)

View File

@@ -1,153 +0,0 @@
## Joystick
The keyboard can be made to be recognized as a joystick HID device by the operating system.
This is enabled by adding `JOYSTICK_ENABLE` to `rules.mk`. You can set this value to `analog`, `digital`, or `no`.
!> Joystick support is not currently available on V-USB devices.
The joystick feature provides two services:
* reading analog input devices (eg. potentiometers)
* sending gamepad HID reports
Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance)
or send gamepad reports based on values computed by the keyboard.
### Analog Input
To use analog input you must first enable it in `rules.mk`:
```makefile
JOYSTICK_ENABLE = analog
```
An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider).
It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor,
which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter).
Depending on which pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated,
feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures.
### Configuring the Joystick
By default, two axes and eight buttons are defined. This can be changed in your `config.h`:
```c
// Max 32
#define JOYSTICK_BUTTON_COUNT 16
// Max 6: X, Y, Z, Rx, Ry, Rz
#define JOYSTICK_AXES_COUNT 3
```
When defining axes for your joystick, you have to provide a definition array. You can do this from your keymap.c file.
A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code.
You have to define an array of type ''joystick_config_t'' and of proper size.
There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU:
* 1 pin: your analog device is directly connected to your device GND and VCC. The only pin used is the ADC pin of your choice.
* 2 pins: your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC.
* 3 pins: both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards.
The configuration of each axis is performed using one of four macros:
* `JOYSTICK_AXIS_VIRTUAL`: no ADC reading must be performed, that value will be provided by keyboard/keymap-level code
* `JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH)`: a voltage will be read on the provided pin, which must be an ADC-capable pin.
* `JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH)`: the provided `OUTPUT_PIN` will be set high before `INPUT_PIN` is read.
* `JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH)`: the `OUTPUT_PIN` will be set high and `GROUND_PIN` will be set low before reading from `INPUT_PIN`.
In any case where an ADC reading takes place (when `INPUT_PIN` is provided), additional `LOW`, `REST` and `HIGH` parameters are used.
These implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127).
In practice, you have to provide the lowest/highest raw ADC reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted `LOW` and `HIGH` to invert the axis.
For instance, an axes configuration can be defined in the following way:
```c
//joystick config
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
[0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285),
[1] = JOYSTICK_AXIS_VIRTUAL
};
```
When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read.
In this example, the first axis will be read from the `A4` pin while `B0` is set high and `A7` is set low, using `analogReadPin()`, whereas the second axis will not be read.
In order to give a value to the second axis, you can do so in any customizable entry point: as an action, in `process_record_user()` or in `matrix_scan_user()`, or even in `joystick_task()` which is called even when no key has been pressed.
You assign a value by writing to `joystick_status.axes[axis_index]` a signed 8-bit value (ranging from -127 to 127). Then it is necessary to assign the flag `JS_UPDATED` to `joystick_status.status` in order for an updated HID report to be sent.
The following example writes two axes based on keypad presses, with `KC_P5` as a precision modifier:
```c
#ifdef ANALOG_JOYSTICK_ENABLE
static uint8_t precision_val = 70;
static uint8_t axesFlags = 0;
enum axes {
Precision = 1,
Axis1High = 2,
Axis1Low = 4,
Axis2High = 8,
Axis2Low = 16
};
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
#ifdef ANALOG_JOYSTICK_ENABLE
// virtual joystick
# if JOYSTICK_AXES_COUNT > 1
case KC_P8:
if (record->event.pressed) {
axesFlags |= Axis2Low;
} else {
axesFlags &= ~Axis2Low;
}
joystick_status.status |= JS_UPDATED;
break;
case KC_P2:
if (record->event.pressed) {
axesFlags |= Axis2High;
} else {
axesFlags &= ~Axis2High;
}
joystick_status.status |= JS_UPDATED;
break;
# endif
case KC_P4:
if (record->event.pressed) {
axesFlags |= Axis1Low;
} else {
axesFlags &= ~Axis1Low;
}
joystick_status.status |= JS_UPDATED;
break;
case KC_P6:
if (record->event.pressed) {
axesFlags |= Axis1High;
} else {
axesFlags &= ~Axis1High;
}
joystick_status.status |= JS_UPDATED;
break;
case KC_P5:
if (record->event.pressed) {
axesFlags |= Precision;
} else {
axesFlags &= ~Precision;
}
joystick_status.status |= JS_UPDATED;
break;
#endif
}
return true;
}
```
### Axis Resolution
By default, the resolution of each axis is 8 bit, giving a range of -127 to +127. If you need higher precision, you can increase it by defining eg. `JOYSTICK_AXES_RESOLUTION 12` in your `config.h`. The resolution must be between 8 and 16.
Note that the supported AVR MCUs have a 10-bit ADC, and 12-bit for most STM32 MCUs.
### Triggering Joystick Buttons
Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured.
To trigger a joystick button, just add the corresponding keycode to your keymap.

View File

@@ -16,7 +16,7 @@ First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Th
## Caveats
Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
Key Lock is only able to hold standard action keys and [One Shot modifier](feature_advanced_keycodes.md#one-shot-keys) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
Switching layers will not cancel the Key Lock.

View File

@@ -1,93 +0,0 @@
# Layers :id=layers
One of the most powerful and well used features of QMK Firmware is the ability to use layers. For most people, this amounts to a function key that allows for different keys, much like what you would see on a laptop or tablet keyboard.
For a detailed explanation of how the layer stack works, checkout [Keymap Overview](keymap.md#keymap-and-layers).
## Switching and Toggling Layers :id=switching-and-toggling-layers
These functions allow you to activate layers in various ways. Note that layers are not generally independent layouts -- multiple layers can be activated at once, and it's typical for layers to use `KC_TRNS` to allow keypresses to pass through to lower layers. When using momentary layer switching with MO(), LM(), TT(), or LT(), make sure to leave the key on the above layers transparent or it may not work as intended.
* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).)
* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated.
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15.
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys.md) for details and additional functionality.
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed).
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
### Caveats :id=caveats
Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Specifically, dual function keys like `LT` and `MT` use a 16 bit keycode. 4 bits are used for the function identifier, the next 12 are divided into the parameters. Layer Tap uses 4 bits for the layer (and is why it's limited to layers 0-15, actually), while Mod Tap does the same, 4 bits for the identifier, 4 bits for which mods are used, and all of them use 8 bits for the keycode. Because of this, the keycode used is limited to `0xFF` (0-255), which are the basic keycodes only.
Expanding this would be complicated, at best. Moving to a 32-bit keycode would solve a lot of this, but would double the amount of space that the keymap matrix uses. And it could potentially cause issues, too. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this.
Additionally, if at least one right-handed modifier is specified in a Mod Tap or Layer Tap, it will cause all modifiers specified to become right-handed, so it is not possible to mix and match the two.
## Working with Layers :id=working-with-layers
Care must be taken when switching layers, it's possible to lock yourself into a layer with no way to deactivate that layer (without unplugging your keyboard.) We've created some guidelines to help users avoid the most common problems.
### Beginners :id=beginners
If you are just getting started with QMK you will want to keep everything simple. Follow these guidelines when setting up your layers:
* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number).
* Arrange your layers in a "tree" layout, with layer 0 as the root. Do not try to enter the same layer from more than one other layer.
* In a layer's keymap, only reference higher-numbered layers. Because layers are processed from the highest-numbered (topmost) active layer down, modifying the state of lower layers can be tricky and error-prone.
### Intermediate Users :id=intermediate-users
Sometimes you need more than one base layer. For example, if you want to switch between QWERTY and Dvorak, switch between layouts for different countries, or switch your layout for different videogames. Your base layers should always be the lowest numbered layers. When you have multiple base layers you should always treat them as mutually exclusive. When one base layer is on the others are off.
### Advanced Users :id=advanced-users
Once you have a good feel for how layers work and what you can do, you can get more creative. The rules listed in the beginner section will help you be successful by avoiding some of the tricker details but they can be constraining, especially for ultra-compact keyboard users. Understanding how layers work will allow you to use them in more advanced ways.
Layers stack on top of each other in numerical order. When determining what a keypress does, QMK scans the layers from the top down, stopping when it reaches the first active layer that is not set to `KC_TRNS`. As a result if you activate a layer that is numerically lower than your current layer, and your current layer (or another layer that is active and higher than your target layer) has something other than `KC_TRNS`, that is the key that will be sent, not the key on the layer you just activated. This is the cause of most people's "why doesn't my layer get switched" problem.
Sometimes, you might want to switch between layers in a macro or as part of a tap dance routine. `layer_on` activates a layer, and `layer_off` deactivates it. More layer-related functions can be found in [action_layer.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/action_layer.h).
## Functions :id=functions
There are a number of functions (and variables) related to how you can use or manipulate the layers.
|Function |Description |
|----------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `layer_state_set(layer_mask)` | Directly sets the layer state (recommended, do not use unless you know what you are doing). |
| `layer_clear()` | Clears all layers (turns them all off). |
| `layer_move(layer)` | Turns specified layer on, and all other layers off. |
| `layer_on(layer)` | Turns specified layer on, leaves all other layers in existing state. |
| `layer_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_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. |
| `layer_debug(layer_mask)` | Prints out the current bit mask and highest active layer to debugger console. |
| `default_layer_set(layer_mask)` | Directly sets the default layer state (recommended, do not use unless you know what you are doing). |
| `default_layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing default layer state. |
| `default_layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing default layer state. |
| `default_layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing default layer state. |
| `default_layer_debug(layer_mask)` | Prints out the current bit mask and highest active default layer to debugger console. |
| [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer) | Sets the default layer and writes it to persistent memory (EEPROM). |
| [`update_tri_layer(x, y, z)`](ref_functions.md#update_tri_layerx-y-z) | Checks if layers `x` and `y` are both on, and sets `z` based on that (on if both on, otherwise off). |
| [`update_tri_layer_state(state, x, y, z)`](ref_functions.md#update_tri_layer_statestate-x-y-z) | Does the same as `update_tri_layer(x, y, z)`, but from `layer_state_set_*` functions. |
In addition to the functions that you can call, there are a number of callback functions that get called every time the layer changes. This passes the layer state to the function, where it can be read or modified.
|Callback |Description |
|-----------------------------------------------------|----------------------------------------------------------------------------------------|
| `layer_state_set_kb(layer_state_t state)` | Callback for layer functions, for keyboard. |
| `layer_state_set_user(layer_state_t state)` | Callback for layer functions, for users. |
| `default_layer_state_set_kb(layer_state_t state)` | Callback for default layer functions, for keyboard. Called on keyboard initialization. |
| `default_layer_state_set_user(layer_state_t state)` | Callback for default layer functions, for users. Called on keyboard initialization. |
?> For additional details on how you can use these callbacks, check out the [Layer Change Code](custom_quantum_functions.md#layer-change-code) document.
It is also possible to check the state of a particular layer using the following functions and macros.
|Function |Description |Aliases
|---------------------------------|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| `layer_state_is(layer)` | Checks if the specified `layer` is enabled globally. | `IS_LAYER_ON(layer)`, `IS_LAYER_OFF(layer)` |
| `layer_state_cmp(state, layer)` | Checks `state` to see if the specified `layer` is enabled. Intended for use in layer callbacks. | `IS_LAYER_ON_STATE(state, layer)`, `IS_LAYER_OFF_STATE(state, layer)` |

View File

@@ -5,7 +5,7 @@ If you've ever used Vim, you know what a Leader key is. If not, you're about to
That's what `KC_LEAD` does. Here's an example:
1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low.
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low. .
* By default, this timeout is how long after pressing `KC_LEAD` to complete your entire sequence. This may be very low for some people. So you may want to increase this timeout. Optionally, you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. This allows you to maintain a low value here, but still be able to use the longer sequences. To enable this option, add `#define LEADER_PER_KEY_TIMING` to your `config.h`.
3. Within your `matrix_scan_user` function, add something like this:
@@ -74,9 +74,9 @@ SEQ_THREE_KEYS(KC_C, KC_C, KC_C) {
## Strict Key Processing
By default, the Leader Key feature will filter the keycode out of [`Mod-Tap`](mod_tap.md) and [`Layer Tap`](feature_layers.md#switching-and-toggling-layers) functions when checking for the Leader sequences. That means if you're using `LT(3, KC_A)`, it will pick this up as `KC_A` for the sequence, rather than `LT(3, KC_A)`, giving a more expected behavior for newer users.
By default, the Leader Key feature will filter the keycode out of [`Mod-Tap`](feature_advanced_keycodes.md#mod-tap) and [`Layer Tap`](feature_advanced_keycodes.md#switching-and-toggling-layers) functions when checking for the Leader sequences. That means if you're using `LT(3, KC_A)`, it will pick this up as `KC_A` for the sequence, rather than `LT(3, KC_A)`, giving a more expected behavior for newer users.
While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by added `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This will then disable the filtering, and you'll need to specify the whole keycode.
While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by added `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This well then disable the filtering, and you'll need to specify the whole keycode.
## Customization

View File

@@ -1,116 +0,0 @@
# LED Indicators
QMK provides methods to read 5 of the LEDs defined in the HID spec:
* Num Lock
* Caps Lock
* Scroll Lock
* Compose
* Kana
There are three ways to get the lock LED state:
* by specifying configuration options within `config.h`
* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
* by calling `led_t host_keyboard_led_state()`
!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
Two more deprecated functions exist that provide the LED state as a `uint8_t`:
* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
* `uint8_t host_keyboard_leds()`
## Configuration Options
To configure the indicators, `#define` these in your `config.h`:
|Define |Default |Description |
|---------------------|-------------|-------------------------------------------|
|`LED_NUM_LOCK_PIN` |*Not defined*|The pin that controls the `Num Lock` LED |
|`LED_CAPS_LOCK_PIN` |*Not defined*|The pin that controls the `Caps Lock` LED |
|`LED_SCROLL_LOCK_PIN`|*Not defined*|The pin that controls the `Scroll Lock` LED|
|`LED_COMPOSE_PIN` |*Not defined*|The pin that controls the `Compose` LED |
|`LED_KANA_PIN` |*Not defined*|The pin that controls the `Kana` LED |
|`LED_PIN_ON_STATE` |`1` |The state of the indicator pins when the LED is "on" - `1` for high, `0` for low|
Unless you are designing your own keyboard, you generally should not need to change the above config options.
## `led_update_*()`
When the configuration options do not provide enough flexibility, the API hooks provided allow custom control of the LED behavior. These functions will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
return `false` when you would prefer not to run the code in `led_update_kb()`.
Some examples include:
- overriding the LEDs to use them for something else like layer indication
- return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
- play a sound when an LED turns on or off.
- return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead.
### Example `led_update_kb()` Implementation
```c
bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state);
if(res) {
// writePin sets the pin high for 1 and low for 0.
// In this example the pins are inverted, setting
// it low/0 turns it on, and high/1 turns the LED off.
// This behavior depends on whether the LED is between the pin
// and VCC or the pin and GND.
writePin(B0, !led_state.num_lock);
writePin(B1, !led_state.caps_lock);
writePin(B2, !led_state.scroll_lock);
writePin(B3, !led_state.compose);
writePin(B4, !led_state.kana);
}
return res;
}
```
### Example `led_update_user()` Implementation
This incomplete example would play a sound if Caps Lock is turned on or off. It returns `true`, because you also want the LEDs to maintain their state.
```c
#ifdef AUDIO_ENABLE
float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
#endif
bool led_update_user(led_t led_state) {
#ifdef AUDIO_ENABLE
static uint8_t caps_state = 0;
if (caps_state != led_state.caps_lock) {
led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
caps_state = led_state.caps_lock;
}
#endif
return true;
}
```
### `led_update_*` Function Documentation
* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
* Keymap: `bool led_update_user(led_t led_state)`
## `host_keyboard_led_state()`
Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
## Setting Physical LED State
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
### Ergodox Boards
The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).

View File

@@ -10,8 +10,7 @@ If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_r
There is basic support for addressable LED matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
LED_MATRIX_ENABLE = yes
LED_MATRIX_DRIVER = IS31FL3731
LED_MATRIX_ENABLE = 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`:

View File

@@ -6,34 +6,34 @@ Macros allow you to send multiple keystrokes when pressing just one key. QMK has
## The New Way: `SEND_STRING()` & `process_record_user`
Sometimes you want a key to type out words or phrases. For the most common situations, we've provided `SEND_STRING()`, which will type out a string (i.e. a sequence of characters) for you. All ASCII characters that are easily translatable to a keycode are supported (e.g. `qmk 123\n\t`).
Sometimes you just want a key to type out words or phrases. For the most common situations we've provided `SEND_STRING()`, which will type out your string (i.e. a sequence of characters) for you. All ASCII characters that are easily translated to a keycode are supported (e.g. `\n\t`).
Here is an example `keymap.c` for a two-key keyboard:
```c
enum custom_keycodes {
QMKBEST = SAFE_RANGE,
QMKBEST = SAFE_RANGE,
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
switch (keycode) {
case QMKBEST:
if (record->event.pressed) {
// when keycode QMKBEST is pressed
SEND_STRING("QMK is the best thing ever!");
} else {
// when keycode QMKBEST is released
}
break;
}
return true;
if (record->event.pressed) {
// when keycode QMKBEST is pressed
SEND_STRING("QMK is the best thing ever!");
} else {
// when keycode QMKBEST is released
}
break;
}
return true;
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = {
{QMKBEST, KC_ESC},
// ...
},
[0] = {
{QMKBEST, KC_ESC}
}
};
```
@@ -49,88 +49,45 @@ You can do that by adding another keycode and adding another case to the switch
```c
enum custom_keycodes {
QMKBEST = SAFE_RANGE,
QMKURL,
MY_OTHER_MACRO,
QMKBEST = SAFE_RANGE,
QMKURL,
MY_OTHER_MACRO
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case QMKBEST:
if (record->event.pressed) {
// when keycode QMKBEST is pressed
SEND_STRING("QMK is the best thing ever!");
} else {
// when keycode QMKBEST is released
}
break;
case QMKURL:
if (record->event.pressed) {
// when keycode QMKURL is pressed
SEND_STRING("https://qmk.fm/\n");
} else {
// when keycode QMKURL is released
}
break;
case MY_OTHER_MACRO:
if (record->event.pressed) {
SEND_STRING(SS_LCTL("ac")); // selects all and copies
}
break;
}
return true;
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = {
{MY_CUSTOM_MACRO, MY_OTHER_MACRO},
// ...
},
};
```
### Advanced Macros
In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance.
In this example, we modify most normal keypresses so that `F22` is pressed before the keystroke is normally sent, and release it __only after__ it's been released.
```c
static uint8_t f22_tracker;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_A ... KC_F21: //notice how it skips over F22
case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys
case QMKBEST:
if (record->event.pressed) {
register_code(KC_F22); //this means to send F22 down
f22_tracker++;
register_code(keycode);
return false;
// when keycode QMKBEST is pressed
SEND_STRING("QMK is the best thing ever!");
} else {
// when keycode QMKBEST is released
}
break;
case QMKURL:
if (record->event.pressed) {
// when keycode QMKURL is pressed
SEND_STRING("https://qmk.fm/\n");
} else {
// when keycode QMKURL is released
}
break;
case MY_OTHER_MACRO:
if (record->event.pressed) {
SEND_STRING(SS_LCTL("ac")); // selects all and copies
}
break;
}
return true;
}
};
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_A ... KC_F21: //notice how it skips over F22
case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys
if (!record->event.pressed) {
f22_tracker--;
if (!f22_tracker) {
unregister_code(KC_F22); //this means to send F22 up
}
}
break;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = {
{MY_CUSTOM_MACRO, MY_OTHER_MACRO}
}
}
};
```
### TAP, DOWN and UP
You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`.
@@ -164,11 +121,11 @@ There's also a couple of mod shortcuts you can use:
* `SS_LCTL(string)`
* `SS_LSFT(string)`
* `SS_LALT(string)` or `SS_LOPT(string)`
* `SS_LALT(string)`
* `SS_LGUI(string)`, `SS_LCMD(string)` or `SS_LWIN(string)`
* `SS_RCTL(string)`
* `SS_RSFT(string)`
* `SS_RALT(string)`, `SS_ROPT(string)` or `SS_ALGR(string)`
* `SS_RALT(string)` or `SS_ALGR(string)`
* `SS_RGUI(string)`, `SS_RCMD(string)` or `SS_RWIN(string)`
These press the respective modifier, send the supplied string and then release the modifier.
@@ -182,9 +139,7 @@ Which would send Left Control+`a` (Left Control down, `a`, Left Control up) - no
By default, it assumes a US keymap with a QWERTY layout; if you want to change that (e.g. if your OS uses software Colemak), include this somewhere in your keymap:
```c
#include "sendstring_colemak.h"
```
#include <sendstring_colemak.h>
### Strings in Memory
@@ -209,7 +164,7 @@ SEND_STRING(".."SS_TAP(X_END));
There are some functions you may find useful in macro-writing. Keep in mind that while you can write some fairly advanced code within a macro, if your functionality gets too complex you may want to define a custom keycode instead. Macros are meant to be simple.
?> You can also use the functions described in [Useful functions](ref_functions.md) for additional functionality. For example `reset_keyboard()` allows you to reset the keyboard as part of a macro.
?> You can also use the functions described in [Useful function](ref_functions.md) for additional functionality. For example `reset_keyboard()` allows you to reset the keyboard as part of a macro.
### `record->event.pressed`

View File

@@ -39,12 +39,10 @@ In your keymap you can use the following keycodes to map key presses to mouse ac
## Configuring mouse keys
Mouse keys supports three different modes to move the cursor:
Mouse keys supports two different modes to move the cursor:
* **Accelerated (default):** Holding movement keys accelerates the cursor until it reaches its maximum speed.
* **Kinetic:** Holding movement keys accelerates the cursor with its speed following a quadratic curve until it reaches its maximum speed.
* **Constant:** Holding movement keys moves the cursor at constant speeds.
* **Combined:** Holding movement keys accelerates the cursor until it reaches its maximum speed, but holding acceleration and movement keys simultaneously moves the cursor at constant speeds.
The same principle applies to scrolling.
@@ -57,12 +55,9 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|Define |Default|Description |
|----------------------------|-------|---------------------------------------------------------|
|`MOUSEKEY_DELAY` |300 |Delay between pressing a movement key and cursor movement|
|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements in milliseconds |
|`MOUSEKEY_MOVE_DELTA` |5 |Step size |
|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements |
|`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached |
|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement |
|`MOUSEKEY_WHEEL_INTERVAL` |100 |Time between wheel movements |
|`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 |
@@ -71,34 +66,9 @@ Tips:
* Setting `MOUSEKEY_DELAY` too low makes the cursor unresponsive. Setting it too high makes small movements difficult.
* For smoother cursor movements, lower the value of `MOUSEKEY_INTERVAL`. If the refresh rate of your display is 60Hz, you could set it to `16` (1/60). As this raises the cursor speed significantly, you may want to lower `MOUSEKEY_MAX_SPEED`.
* Setting `MOUSEKEY_TIME_TO_MAX` or `MOUSEKEY_WHEEL_TIME_TO_MAX` to `0` will disable acceleration for the cursor or scrolling respectively. This way you can make one of them constant while keeping the other accelerated, which is not possible in constant speed mode.
* Setting `MOUSEKEY_WHEEL_INTERVAL` too low will make scrolling too fast. Setting it too high will make scrolling too slow when the wheel key is held down.
Cursor acceleration uses the same algorithm as the X Window System MouseKeysAccel feature. You can read more about it [on Wikipedia](https://en.wikipedia.org/wiki/Mouse_keys).
### Kinetic Mode
This is an extension of the accelerated mode. The kinetic mode uses a quadratic curve on the cursor speed which allows precise movements at the beginning and allows to cover large distances by increasing cursor speed quickly thereafter. You can adjust the cursor and scrolling acceleration using the following settings in your keymaps `config.h` file:
|Define |Default |Description |
|--------------------------------------|---------|---------------------------------------------------------------|
|`MK_KINETIC_SPEED` |undefined|Enable kinetic mode |
|`MOUSEKEY_DELAY` |8 |Delay between pressing a movement key and cursor movement |
|`MOUSEKEY_INTERVAL` |8 |Time between cursor movements in milliseconds |
|`MOUSEKEY_MOVE_DELTA` |25 |Step size for accelerating from initial to base speed |
|`MOUSEKEY_INITIAL_SPEED` |100 |Initial speed of the cursor in pixel per second |
|`MOUSEKEY_BASE_SPEED` |1000 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_DECELERATED_SPEED` |400 |Decelerated cursor speed |
|`MOUSEKEY_ACCELERATED_SPEED` |3000 |Accelerated cursor speed |
|`MOUSEKEY_WHEEL_INITIAL_MOVEMENTS` |16 |Initial number of movements of the mouse wheel |
|`MOUSEKEY_WHEEL_BASE_MOVEMENTS` |32 |Maximum number of movements at which acceleration stops |
|`MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS`|48 |Accelerated wheel movements |
|`MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS`|8 |Decelerated wheel movements |
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 `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
### Constant mode
In this mode you can define multiple different speeds for both the cursor and the mouse wheel. There is no acceleration. `KC_ACL0`, `KC_ACL1` and `KC_ACL2` change the cursor and scroll speed to their respective setting.
@@ -147,26 +117,3 @@ Use the following settings if you want to adjust cursor movement or scrolling:
|`MK_W_INTERVAL_1` |120 |Time between scroll steps (`KC_ACL1`) |
|`MK_W_OFFSET_2` |1 |Scroll steps per scroll action (`KC_ACL2`) |
|`MK_W_INTERVAL_2` |20 |Time between scroll steps (`KC_ACL2`) |
### Combined mode
This mode functions like **Accelerated** mode, however, you can hold `KC_ACL0`, `KC_ACL1` and `KC_ACL2`
to momentarily (while held) set the cursor and scroll speeds to constant speeds. When no acceleration
keys are held, this mode is identical to **Accelerated** mode, and can be modified using all of the
relevant settings.
* **KC_ACL0:** This acceleration sets your cursor to the slowest possible speed. This is useful for very
small and detailed movements of the cursor.
* **KC_ACL1:** This acceleration sets your cursor to half the maximum (user defined) speed.
* **KC_ACL2:** This acceleration sets your cursor to the maximum (computer defined) speed. This is
useful for moving the cursor large distances without much accuracy.
To use constant speed mode, you must at least define `MK_COMBINED` in your keymaps `config.h` file:
```c
#define MK_COMBINED
```
## Use with PS/2 Mouse and Pointing Device
Mouse keys button state is shared with [PS/2 mouse](feature_ps2_mouse.md) and [pointing device](feature_pointing_device.md) so mouse keys button presses can be used for clicks and drags.

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