summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_summary.md5
-rw-r--r--docs/cli.md31
-rw-r--r--docs/coding_conventions_c.md58
-rw-r--r--docs/coding_conventions_python.md314
-rw-r--r--docs/config_options.md5
-rw-r--r--docs/contributing.md58
-rw-r--r--docs/faq_build.md10
-rw-r--r--docs/faq_debug.md1
-rw-r--r--docs/feature_advanced_keycodes.md16
-rw-r--r--docs/feature_backlight.md8
-rw-r--r--docs/feature_combo.md32
-rw-r--r--docs/feature_encoders.md1
-rw-r--r--docs/feature_oled_driver.md2
-rw-r--r--docs/feature_space_cadet.md1
-rw-r--r--docs/feature_split_keyboard.md185
-rw-r--r--docs/feature_unicode.md68
-rw-r--r--docs/features.md1
-rw-r--r--docs/flashing.md25
-rw-r--r--docs/getting_started_vagrant.md46
-rw-r--r--docs/i2c_driver.md20
-rw-r--r--docs/newbs_flashing.md4
-rw-r--r--docs/python_development.md45
22 files changed, 818 insertions, 118 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index 8a40ccd7f2..56184f44de 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -8,6 +8,7 @@
* [QMK Basics](README.md)
* [QMK Introduction](getting_started_introduction.md)
+ * [QMK CLI](cli.md)
* [Contributing to QMK](contributing.md)
* [How to Use Github](getting_started_github.md)
* [Getting Help](getting_started_getting_help.md)
@@ -34,6 +35,8 @@
* [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)
@@ -41,6 +44,7 @@
* [Useful Functions](ref_functions.md)
* [Configurator Support](reference_configurator_support.md)
* [info.json Format](reference_info_json.md)
+ * [Python Development](python_development.md)
* [Features](features.md)
* [Basic Keycodes](keycodes_basic.md)
@@ -73,6 +77,7 @@
* [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)
diff --git a/docs/cli.md b/docs/cli.md
new file mode 100644
index 0000000000..0365f2c9c8
--- /dev/null
+++ b/docs/cli.md
@@ -0,0 +1,31 @@
+# QMK CLI
+
+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 help you work with QMK:
+
+* `qmk compile-json`
+
+# Setup
+
+Simply add the `qmk_firmware/bin` directory to your `PATH`. You can run the `qmk` commands from any directory.
+
+```
+export PATH=$PATH:$HOME/qmk_firmware/bin
+```
+
+You may want to add this to your `.profile`, `.bash_profile`, `.zsh_profile`, or other shell startup scripts.
+
+# Commands
+
+## `qmk compile-json`
+
+This command allows you to compile JSON files you have downloaded from <https://config.qmk.fm>.
+
+**Usage**:
+
+```
+qmk compile-json mine.json
+```
diff --git a/docs/coding_conventions_c.md b/docs/coding_conventions_c.md
new file mode 100644
index 0000000000..cbddedf8b0
--- /dev/null
+++ b/docs/coding_conventions_c.md
@@ -0,0 +1,58 @@
+# Coding Conventions (C)
+
+Most of our style is pretty easy to pick up on, but right now it's not entirely consistent. You should match the style of the code surrounding your change, but if that code is inconsistent or unclear use the following guidelines:
+
+* We indent using four (4) spaces (soft tabs)
+* We use a modified One True Brace Style
+ * Opening Brace: At the end of the same line as the statement that opens the block
+ * Closing Brace: Lined up with the first character of the statement that opens the block
+ * Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
+ * Optional Braces: Always include optional braces.
+ * Good: if (condition) { return false; }
+ * Bad: if (condition) return false;
+* We encourage use of C style comments: `/* */`
+ * Think of them as a story describing the feature
+ * Use them liberally to explain why particular decisions were made.
+ * Do not write obvious comments
+ * If you not sure if a comment is obvious, go ahead and include it.
+* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
+* We use `#pragma once` at the start of header files rather than old-style include guards (`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)
+* 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`.
+ * 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:
+
+```c
+/* Enums for foo */
+enum foo_state {
+ FOO_BAR,
+ FOO_BAZ,
+};
+
+/* Returns a value */
+int foo(void) {
+ if (some_condition) {
+ return FOO_BAR;
+ } else {
+ return -1;
+ }
+}
+```
+
+# Auto-formatting with clang-format
+
+[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) is part of LLVM and can automatically format your code for you, because ain't nobody got time to do it manually. We supply a configuration file for it that applies most of the coding conventions listed above. It will only change whitespace and newlines, so you will still have to remember to include optional braces yourself.
+
+Use the [full LLVM installer](http://llvm.org/builds/) to get clang-format on Windows, or use `sudo apt install clang-format` on Ubuntu.
+
+If you run it from the command-line, pass `-style=file` as an option and it will automatically find the .clang-format configuration file in the QMK root directory.
+
+If you use VSCode, the standard C/C++ plugin supports clang-format, alternatively there is a [separate extension](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) for it.
+
+Some things (like LAYOUT macros) are destroyed by clang-format, so either don't run it on those files, or wrap the sensitive code in `// clang-format off` and `// clang-format on`.
diff --git a/docs/coding_conventions_python.md b/docs/coding_conventions_python.md
new file mode 100644
index 0000000000..c7743050e2
--- /dev/null
+++ b/docs/coding_conventions_python.md
@@ -0,0 +1,314 @@
+# Coding Conventions (Python)
+
+Most of our style follows PEP8 with some local modifications to make things less nit-picky.
+
+* 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
+ * Use them liberally to explain why particular decisions were made.
+ * Do not write obvious comments
+ * If you not sure if a comment is obvious, go ahead and include it.
+* We require useful docstrings for all functions.
+* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
+* Some of our practices conflict with the wider python community to make our codebase more approachable to non-pythonistas.
+
+# YAPF
+
+You can use [yapf](https://github.com/google/yapf) to style your code. We provide a config in [setup.cfg](setup.cfg).
+
+# Imports
+
+We don't have a hard and fast rule for when to use `import ...` vs `from ... import ...`. Understandability and maintainability is our ultimate goal.
+
+Generally we prefer to import specific function and class names from a module to keep code shorter and easier to understand. Sometimes this results in a name that is ambiguous, and in such cases we prefer to import the module instead. You should avoid using the "as" keyword when importing, unless you are importing a compatability module.
+
+Imports should be one line per module. We group import statements together using the standard python rules- system, 3rd party, local.
+
+Do not use `from foo import *`. Supply a list of objects you want to import instead, or import the whole module.
+
+## Import Examples
+
+Good:
+
+```
+from qmk import effects
+
+effects.echo()
+```
+
+Bad:
+
+```
+from qmk.effects import echo
+
+echo() # It's unclear where echo comes from
+```
+
+Good:
+
+```
+from qmk.keymap import compile_firmware
+
+compile_firmware()
+```
+
+OK, but the above is better:
+
+```
+import qmk.keymap
+
+qmk.keymap.compile_firmware()
+```
+
+# Statements
+
+One statement per line.
+
+Even when allowed (EG `if foo: bar`) we do not combine 2 statements onto a single line.
+
+# Naming
+
+`module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, `function_parameter_name`, `local_var_name`.
+
+Function names, variable names, and filenames should be descriptive; eschew abbreviation. In particular, do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word.
+
+Always use a .py filename extension. Never use dashes.
+
+## Names to Avoid
+
+* single character names except for counters or iterators. You may use "e" as an exception identifier in try/except statements.
+* dashes (-) in any package/module name
+* __double_leading_and_trailing_underscore__ names (reserved by Python)
+
+# Docstrings
+
+To maintain consistency with our docstrings we've set out the following guidelines.
+
+* Use markdown formatting
+* Always use triple-dquote docstrings with at least one linebreak: `"""\n"""`
+* First line is a short (< 70 char) description of what the function does
+* If you need more in your docstring leave a blank line between the description and the rest.
+* Start indented lines at the same indent level as the opening triple-dquote
+* Document all function arguments using the format described below
+* If present, Args:, Returns:, and Raises: should be the last three things in the docstring, separated by a blank line each.
+
+## Simple docstring example
+
+```
+def my_awesome_function():
+ """Return the number of seconds since 1970 Jan 1 00:00 UTC.
+ """
+ return int(time.time())
+```
+
+## Complex docstring example
+
+```
+def my_awesome_function():
+ """Return the number of seconds since 1970 Jan 1 00:00 UTC.
+
+ This function always returns an integer number of seconds.
+ """
+ return int(time.time())
+```
+
+## Function arguments docstring example
+
+```
+def my_awesome_function(start=None, offset=0):
+ """Return the number of seconds since 1970 Jan 1 00:00 UTC.
+
+ This function always returns an integer number of seconds.
+
+
+ Args:
+ start
+ The time to start at instead of 1970 Jan 1 00:00 UTC
+
+ offset
+ Return an answer that has this number of seconds subtracted first
+
+ Returns:
+ An integer describing a number of seconds.
+
+ Raises:
+ ValueError
+ When `start` or `offset` are not positive numbers
+ """
+ if start < 0 or offset < 0:
+ raise ValueError('start and offset must be positive numbers.')
+
+ if not start:
+ start = time.time()
+
+ return int(start - offset)
+```
+
+# Exceptions
+
+Exceptions are used to handle exceptional situations. They should not be used for flow control. This is a break from the python norm of "ask for forgiveness." If you are catching an exception it should be to handle a situation that is unusual.
+
+If you use a catch-all exception for any reason you must log the exception and stacktrace using cli.log.
+
+Make your try/except blocks as short as possible. If you need a lot of try statements you may need to restructure your code.
+
+# Tuples
+
+When defining one-item tuples always include a trailing comma so that it is obvious you are using a tuple. Do not rely on implicit one-item tuple unpacking. Better still use a list which is unambiguous.
+
+This is particularly important when using the printf-style format strings that are commonly used.
+
+# Lists and Dictionaries
+
+We have configured YAPF to differentiate between sequence styles with a trailing comma. When a trailing comma is omitted YAPF will format the sequence as a single line. When a trailing comma is included YAPF will format the sequence with one item per line.
+
+You should generally prefer to keep short definition on a single line. Break out to multiple lines sooner rather than later to aid readability and maintainability.
+
+# Parentheses
+
+Avoid excessive parentheses, but do use parentheses to make code easier to understand. Do not use them in return statements unless you are explicitly returning a tuple, or it is part of a math expression.
+
+# Format Strings
+
+We generally prefer printf-style format strings. Example:
+
+```
+name = 'World'
+print('Hello, %s!' % (name,))
+```
+
+This style is used by the logging module, which we make use of extensively, and we have adopted it in other places for consistency. It is also more familiar to C programmers, who are a big part of our casual audience.
+
+Our included CLI module has support for using these without using the percent (%) operator. Look at `cli.echo()` and the various `cli.log` functions (EG, `cli.log.info()`) for more details.
+
+# Comprehensions & Generator Expressions
+
+We encourage the liberal use of comprehensions and generators, but do not let them get too complex. If you need complexity fall back to a for loop that is easier to understand.
+
+# Lambdas
+
+OK to use but probably should be avoided. With comprehensions and generators the need for lambdas is not as strong as it once was.
+
+# Conditional Expressions
+
+OK in variable assignment, but otherwise should be avoided.
+
+Conditional expressions are if statements that are in line with code. For example:
+
+```
+x = 1 if cond else 2
+```
+
+It's generally not a good idea to use these as function arguments, sequence items, etc. It's too easy to overlook.
+
+# Default Argument Values
+
+Encouraged, but values must be immutable objects.
+
+When specifying default values in argument lists always be careful to specify objects that can't be modified in place. If you use a mutable object the changes you make will persist between calls, which is usually not what you want. Even if that is what you intend to do it is confusing for others and will hinder understanding.
+
+Bad:
+
+```
+def my_func(foo={}):
+ pass
+```
+
+Good:
+
+```
+def my_func(foo=None):
+ if not foo:
+ foo = {}
+```
+
+# Properties
+
+Always use properties instead of getter and setter functions.
+
+```
+class Foo(object):
+ def __init__(self):
+ self._bar = None
+
+ @property
+ def bar(self):
+ return self._bar
+
+ @bar.setter
+ def bar(self, bar):
+ self._bar = bar
+```
+
+# True/False Evaluations
+
+You should generally prefer the implicit True/False evaluation in if statements, rather than checking equivalency.
+
+Bad:
+
+```
+if foo == True:
+ pass
+
+if bar == False:
+ pass
+```
+
+Good:
+
+```
+if foo:
+ pass
+
+if not bar:
+ pass
+```
+
+# Decorators
+
+Use when appropriate. Try to avoid too much magic unless it helps with understanding.
+
+# Threading and Multiprocessing
+
+Should be avoided. If you need this you will have to make a strong case before we merge your code.
+
+# Power Features
+
+Python is an extremely flexible language and gives you many fancy features such as custom metaclasses, access to bytecode, on-the-fly compilation, dynamic inheritance, object reparenting, import hacks, reflection, modification of system internals, etc.
+
+Don't use these.
+
+Performance is not a critical concern for us, and code understandability is. We want our codebase to be approachable by someone who only has a day or two to play with it. These features generally come with a cost to easy understanding, and we would prefer to have code that can be readily understood over faster or more compact code.
+
+Note that some standard library modules use these techniques and it is ok to make use of those modules. But please keep readability and understandability in mind when using them.
+
+# Type Annotated Code
+
+For now we are not using any type annotation system, and would prefer that code remain unannotated. We may revisit this in the future.
+
+# Function length
+
+Prefer small and focused functions.
+
+We recognize that long functions are sometimes appropriate, so no hard limit is placed on function length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program.
+
+Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code.
+
+You could find long and complicated functions when working with some code. Do not be intimidated by modifying existing code: if working with such a function proves to be difficult, you find that errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces.
+
+# FIXMEs
+
+It is OK to leave FIXMEs in code. Why? Encouraging people to at least document parts of code that need to be thought out more (or that are confusing) is better than leaving this code undocumented.
+
+All FIXMEs should be formatted like:
+
+```
+FIXME(username): Revisit this code when the frob feature is done.
+```
+
+...where username is your GitHub username.
+
+# Unit Tests
+
+These are good. We should have some one day.
diff --git a/docs/config_options.md b/docs/config_options.md
index eb0a441ccc..3012dcdcff 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -171,8 +171,8 @@ If you define these options you will enable the associated feature, which may in
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
* `#define TAP_CODE_DELAY 100`
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds.
-* `#define TAP_HOLD_CAPS_DELAY 200`
- * Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 200ms if not defined.
+* `#define TAP_HOLD_CAPS_DELAY 80`
+ * Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 80 ms if not defined. For macOS, you may want to set this to 200 or higher.
## RGB Light Configuration
@@ -289,6 +289,7 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
* `halfkay`
* `caterina`
* `bootloadHID`
+ * `USBasp`
## Feature Options
diff --git a/docs/contributing.md b/docs/contributing.md
index 7d1a9691cf..761bc9959b 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -54,62 +54,10 @@ Never made an open source contribution before? Wondering how contributions work
# Coding Conventions
-Most of our style is pretty easy to pick up on, but right now it's not entirely consistent. You should match the style of the code surrounding your change, but if that code is inconsistent or unclear use the following guidelines:
-
-* We indent using four (4) spaces (soft tabs)
-* We use a modified One True Brace Style
- * Opening Brace: At the end of the same line as the statement that opens the block
- * Closing Brace: Lined up with the first character of the statement that opens the block
- * Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
- * Optional Braces: Always include optional braces.
- * Good: if (condition) { return false; }
- * Bad: if (condition) return false;
-* We encourage use of C style comments: `/* */`
- * Think of them as a story describing the feature
- * Use them liberally to explain why particular decisions were made.
- * Do not write obvious comments
- * If you not sure if a comment is obvious, go ahead and include it.
-* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
-* We use `#pragma once` at the start of header files rather than old-style include guards (`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)
-* 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`.
- * 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:
+Most of our style is pretty easy to pick up on. If you are familiar with either C or Python you should not have too much trouble with our local styles.
-```c
-/* Enums for foo */
-enum foo_state {
- FOO_BAR,
- FOO_BAZ,
-};
-
-/* Returns a value */
-int foo(void) {
- if (some_condition) {
- return FOO_BAR;
- } else {
- return -1;
- }
-}
-```
-
-# Auto-formatting with clang-format
-
-[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) is part of LLVM and can automatically format your code for you, because ain't nobody got time to do it manually. We supply a configuration file for it that applies most of the coding conventions listed above. It will only change whitespace and newlines, so you will still have to remember to include optional braces yourself.
-
-Use the [full LLVM installer](http://llvm.org/builds/) to get clang-format on Windows, or use `sudo apt install clang-format` on Ubuntu.
-
-If you run it from the command-line, pass `-style=file` as an option and it will automatically find the .clang-format configuration file in the QMK root directory.
-
-If you use VSCode, the standard C/C++ plugin supports clang-format, alternatively there is a [separate extension](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) for it.
-
-Some things (like LAYOUT macros) are destroyed by clang-format, so either don't run it on those files, or wrap the sensitive code in `// clang-format off` and `// clang-format on`.
+* [Coding Conventions - C](coding_conventions_c.md)
+* [Coding Conventions - Python](coding_conventions_python.md)
# General Guidelines
diff --git a/docs/faq_build.md b/docs/faq_build.md
index 23d6a67021..bcf017a9b2 100644
--- a/docs/faq_build.md
+++ b/docs/faq_build.md
@@ -49,15 +49,13 @@ Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices m
## Unknown Device for DFU Bootloader
-If you're using Windows to flash your keyboard, and you are running into issues, check the Device Manager. If you see an "Unknown Device" when the keyboard is in "bootloader mode", then you may have a driver issue.
+Issues encountered when flashing keyboards on Windows are most often due to having the wrong drivers installed for the bootloader.
-Re-running the installation script for MSYS2 may help (eg run `./util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue.
+Re-running the installation script for MSYS2 may help (eg run `util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package.
-If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, find the device in question, and select the `WinUSB` option, and hit "Reinstall driver". Once you've done that, try flashing your board, again. If that doesn't work, try all of the options, until one works.
+If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, and run it on the system. Then, you will need to reset your board into bootloader mode. After that, locate the device in question. If the device doesn't show up in the list (or nothing shows up in the list), you may need to enable the `List all devices` option in the `Options` menu.
-?> There isn't a best option for which driver should be used here. Some options work better on some systems than others. libUSB and WinUSB seem to be the best options here.
-
-If the bootloader doesn't show up in the list for devices, you may need to enable the "List all devices" option in the `Options` menu, and then find the bootloader in question.
+From here, you will need to know what type of controller the board is using. You may see it listed in the Device Manager as `ATmega32U4` device (which is an AVR board), or an `STM32` device (Which is an ARM board). For AVR boards, use `libusb-win32` for the driver. For ARM boards, use the `WinUSB` driver. Once the correct driver type has been selected, click on the `Replace Driver` button, unplug your board, plug it back in, and reset it again.
## WINAVR is Obsolete
diff --git a/docs/faq_debug.md b/docs/faq_debug.md
index 7c1690d13f..f6cc729b61 100644
--- a/docs/faq_debug.md
+++ b/docs/faq_debug.md
@@ -87,6 +87,7 @@ Size after:
- EEPROM has around a 100000 write cycle. You shouldn't rewrite the
firmware repeatedly and continually; that'll burn the EEPROM
eventually.
+
## NKRO Doesn't work
First you have to compile firmware with this build option `NKRO_ENABLE` in **Makefile**.
diff --git a/docs/feature_advanced_keycodes.md b/docs/feature_advanced_keycodes.md
index a6ddf458cc..f748ccd70c 100644
--- a/docs/feature_advanced_keycodes.md
+++ b/docs/feature_advanced_keycodes.md
@@ -256,10 +256,10 @@ If you press a Mod Tap key, tap another key (press and release) and then release
For Instance:
-- `SHFT_T(KC_A)` Down
+- `SFT_T(KC_A)` Down
- `KC_X` Down
- `KC_X` Up
-- `SHFT_T(KC_A)` 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`).
@@ -279,9 +279,9 @@ Setting `Ignore Mod Tap Interrupt` requires holding both keys for the `TAPPING_
For Instance:
-- `SHFT_T(KC_A)` Down
+- `SFT_T(KC_A)` Down
- `KC_X` Down
-- `SHFT_T(KC_A)` Up
+- `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`).
@@ -303,11 +303,11 @@ When the user holds a key after tap, this repeats the tapped key rather to hold
Example:
-- SHFT_T(KC_A) Down
-- SHFT_T(KC_A) Up
-- SHFT_T(KC_A) Down
+- SFT_T(KC_A) Down
+- SFT_T(KC_A) Up
+- SFT_T(KC_A) Down
- wait more than tapping term...
-- SHFT_T(KC_A) Up
+- 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.
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index b06db89e4d..64c663076b 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -65,7 +65,7 @@ To change the behaviour of the backlighting, `#define` these in your `config.h`:
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|`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 15 excluding off) |
+|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
@@ -73,8 +73,10 @@ To change the behaviour of the backlighting, `#define` these in your `config.h`:
## 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, *low*.
-Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case you must `#define BACKLIGHT_ON_STATE 1`, so that when the transistor is on, the pin is driven *high* instead.
+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
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index 4cb1bcda08..9db7be5119 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -59,19 +59,12 @@ void process_combo_event(uint8_t combo_index, bool pressed) {
switch(combo_index) {
case ZC_COPY:
if (pressed) {
- register_code(KC_LCTL);
- register_code(KC_C);
- unregister_code(KC_C);
- unregister_code(KC_LCTL);
+ tap_code16(LCTL(KC_C));
}
break;
-
case XV_PASTE:
if (pressed) {
- register_code(KC_LCTL);
- register_code(KC_V);
- unregister_code(KC_V);
- unregister_code(KC_LCTL);
+ tap_code16(LCTL(KC_V));
}
break;
}
@@ -87,3 +80,24 @@ If you're using long combos, or even longer combos, you may run into issues with
In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file.
You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`.
+
+## Keycodes
+
+You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game.
+
+|Keycode |Description |
+|----------|---------------------------------|
+|`CMB_ON` |Turns on Combo feature |
+|`CMB_OFF` |Turns off Combo feature |
+|`CMB_TOG` |Toggles Combo feature on and off |
+
+## User callbacks
+
+In addition to the keycodes, there are a few functions that you can use to set the status, or check it:
+
+|Function |Description |
+|-----------|--------------------------------------------------------------------|
+| `combo_enable()` | Enables the combo feature |
+| `combo_disable()` | Disables the combo feature, and clears the combo buffer |
+| `combo_toggle()` | Toggles the state of the combo feature |
+| `is_combo_enabled()` | Returns the status of the combo feature state (true or false) |
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 9ac97a9a16..bb2d538e7e 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -6,7 +6,6 @@ Basic encoders are supported by adding this to your `rules.mk`:
and this to your `config.h`:
- #define NUMBER_OF_ENCODERS 1
#define ENCODERS_PAD_A { B12 }
#define ENCODERS_PAD_B { B13 }
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled