summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/breaking_changes.md1
-rw-r--r--docs/compatible_microcontrollers.md2
-rw-r--r--docs/config_options.md2
-rw-r--r--docs/data_driven_config.md4
-rw-r--r--docs/feature_auto_shift.md47
-rw-r--r--docs/feature_autocorrect.md13
-rw-r--r--docs/feature_backlight.md346
-rw-r--r--docs/feature_bluetooth.md10
-rw-r--r--docs/feature_haptic_feedback.md45
-rw-r--r--docs/feature_hd44780.md84
-rw-r--r--docs/feature_key_overrides.md27
-rw-r--r--docs/feature_led_matrix.md6
-rw-r--r--docs/feature_mouse_keys.md3
-rw-r--r--docs/feature_rawhid.md153
-rw-r--r--docs/feature_rgb_matrix.md4
-rw-r--r--docs/feature_rgblight.md31
-rw-r--r--docs/feature_send_string.md60
-rw-r--r--docs/feature_tap_dance.md2
-rw-r--r--docs/feature_unicode.md8
-rw-r--r--docs/flashing.md23
-rw-r--r--docs/getting_started_make_guide.md2
-rw-r--r--docs/i2c_driver.md50
-rw-r--r--docs/ja/data_driven_config.md4
-rw-r--r--docs/keycodes.md4
-rw-r--r--docs/spi_driver.md40
-rw-r--r--docs/tap_hold.md25
-rw-r--r--docs/uart_driver.md32
27 files changed, 647 insertions, 381 deletions
diff --git a/docs/breaking_changes.md b/docs/breaking_changes.md
index e660182c32..f4560b746f 100644
--- a/docs/breaking_changes.md
+++ b/docs/breaking_changes.md
@@ -119,6 +119,7 @@ This happens immediately after the previous `develop` branch is merged to `maste
* `git commit -m 'Branch point for <DATE> Breaking Change'`
* `git tag breakpoint_<YYYY>_<MM>_<DD>`
* `git push upstream breakpoint_<YYYY>_<MM>_<DD>`
+ * `git push upstream develop`
* All submodules under `lib` now need to be checked against their QMK-based forks:
* `git submodule foreach git log -n1`
diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
index cc9c0b7f92..197033f78b 100644
--- a/docs/compatible_microcontrollers.md
+++ b/docs/compatible_microcontrollers.md
@@ -43,6 +43,8 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
+ * [STM32H723](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
+ * [STM32H733](https://www.st.com/en/microcontrollers-microprocessors/stm32h723-733.html)
* [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L422](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L432](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
diff --git a/docs/config_options.md b/docs/config_options.md
index 4698260118..8119b9e356 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -439,7 +439,7 @@ Use these to enable or disable building certain features. The more you have enab
* `UNICODE_ENABLE`
* Unicode
* `BLUETOOTH_ENABLE`
- * Current options are BluefruitLE, RN42
+ * Current options are bluefruit_le, rn42
* `SPLIT_KEYBOARD`
* Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
* `CUSTOM_MATRIX`
diff --git a/docs/data_driven_config.md b/docs/data_driven_config.md
index ba287f5688..b288f9901a 100644
--- a/docs/data_driven_config.md
+++ b/docs/data_driven_config.md
@@ -79,8 +79,8 @@ If you are not sure how to edit this file or are not comfortable with Python [op
The final piece of the puzzle is providing your new option to the build system. This is done by generating two files:
-* `.build/obj_<keyboard>/src/info_config.h`
-* `.build/obj_<keyboard>/src/rules.mk`
+* `.build/obj_<keyboard>_<keymap>/src/info_config.h`
+* `.build/obj_<keyboard>_<keymap>/src/rules.mk`
These two files are generated by the code here:
diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
index 1719807e26..6241cbaeb1 100644
--- a/docs/feature_auto_shift.md
+++ b/docs/feature_auto_shift.md
@@ -133,7 +133,17 @@ groups in the below fallback switch.
### NO_AUTO_SHIFT_SPECIAL (simple define)
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
-and /?
+/?, and the KC_TAB.
+
+### NO_AUTO_SHIFT_TAB (simple define)
+
+Do not Auto Shift KC_TAB but leave Auto Shift enabled for the other special
+characters.
+
+### NO_AUTO_SHIFT_SYMBOLS (simple define)
+
+Do not Auto Shift symbol keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
+and /?.
### NO_AUTO_SHIFT_NUMERIC (simple define)
@@ -143,9 +153,13 @@ Do not Auto Shift numeric keys, zero through nine.
Do not Auto Shift alpha characters, which include A through Z.
+### AUTO_SHIFT_ENTER (simple define)
+
+Auto Shift the enter key.
+
### Auto Shift Per Key
-There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
+There are functions that allows you to determine which keys should be autoshifted, much like the tap-hold keys.
The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`:
@@ -172,9 +186,15 @@ bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
case KC_1 ... KC_0:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
+# ifndef NO_AUTO_SHIFT_TAB
case KC_TAB:
- case KC_MINUS ... KC_SLASH:
- case KC_NONUS_BACKSLASH:
+# endif
+# ifndef NO_AUTO_SHIFT_SYMBOLS
+ case AUTO_SHIFT_SYMBOLS:
+# endif
+# endif
+# ifdef AUTO_SHIFT_ENTER
+ case KC_ENT:
# endif
return true;
}
@@ -192,6 +212,25 @@ Enables keyrepeat.
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
+
+### AUTO_SHIFT_ALPHA (predefined key group)
+
+A predefined group of keys representing A through Z.
+
+### AUTO_SHIFT_NUMERIC (predefined key group)
+
+A predefined group of keys representing 0 through 9. Note, these are defined as
+1 through 0 since that is the order they normally appear in.
+
+### AUTO_SHIFT_SYMBOLS (predefined key group)
+
+A predefined group of keys representing symbolic characters which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
+and /?.
+
+### AUTO_SHIFT_SPECIAL (predefined key group)
+
+A predefined group of keys that combines AUTO_SHIFT_SYMBOLS and KC_TAB.
+
## Custom Shifted Values
Especially on small keyboards, the default shifted value for many keys is not
diff --git a/docs/feature_autocorrect.md b/docs/feature_autocorrect.md
index 9f80c93f82..3a0a49095c 100644
--- a/docs/feature_autocorrect.md
+++ b/docs/feature_autocorrect.md
@@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
### Apply Autocorrect
-Additionally, `apply_autocorrect(uint8_t backspaces, const char *str)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word).
+Additionally, `apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word), and the typo and corrected strings (complete words).
+
+?> Due to the way code works (no notion of words, just a stream of letters), the `typo` and `correct` strings are a best bet and could be "wrong". For example you may get `wordtpyo` & `wordtypo` instead of the expected `tpyo` & `typo`.
#### Apply Autocorrect Example
@@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut
float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
#endif
-bool apply_autocorrect(uint8_t backspaces, const char *str) {
+bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef AUDIO_ENABLE
PLAY_SONG(autocorrect_song);
#endif
@@ -223,15 +225,18 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) {
?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters.
-!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` or `SEND_STRING`.
+!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` nor `SEND_STRING`.
You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
```c
-bool apply_autocorrect(uint8_t backspaces, const char *str) {
+bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef OLED_ENABLE
oled_write_P(PSTR("Auto-corrected"), false);
#endif
+#ifdef CONSOLE_ENABLE
+ printf("'%s' was corrected to '%s'\n", typo, correct);
+#endif
return true;
}
```
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index 24057c608f..d032c33f18 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -1,12 +1,12 @@
# Backlighting :id=backlighting
-Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
+Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB Underglow](feature_rgblight.md) and [RGB Matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
-The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
+## Usage :id=usage
-Most keyboards have backlighting enabled by default if they support it, but if it is not working for you, check that your `rules.mk` includes the following:
+Most keyboards have backlighting enabled by default if they support it, but if it is not working for you (or you have added support), check that your `rules.mk` includes the following:
```make
BACKLIGHT_ENABLE = yes
@@ -14,57 +14,23 @@ BACKLIGHT_ENABLE = yes
## Keycodes :id=keycodes
-Once enabled, the following keycodes below can be used to change the backlight level.
+|Key |Aliases |Description |
+|-------------------------------|---------|-----------------------------------|
+|`QK_BACKLIGHT_TOGGLE` |`BL_TOGG`|Turn the backlight on or off |
+|`QK_BACKLIGHT_STEP` |`BL_STEP`|Cycle through backlight levels |
+|`QK_BACKLIGHT_ON` |`BL_ON` |Set the backlight to max brightness|
+|`QK_BACKLIGHT_OFF` |`BL_OFF` |Turn the backlight off |
+|`QK_BACKLIGHT_UP` |`BL_UP` |Increase the backlight level |
+|`QK_BACKLIGHT_DOWN` |`BL_DOWN`|Decrease the backlight level |
+|`QK_BACKLIGHT_TOGGLE_BREATHING`|`BL_BRTG`|Toggle backlight breathing |
-| Key | Aliases | Description |
-|---------------------------------|-----------|-------------------------------------|
-| `QK_BACKLIGHT_TOGGLE` | `BL_TOGG` | Turn the backlight on or off |
-| `QK_BACKLIGHT_STEP` | `BL_STEP` | Cycle through backlight levels |
-| `QK_BACKLIGHT_ON` | `BL_ON` | Set the backlight to max brightness |
-| `QK_BACKLIGHT_OFF` | `BL_OFF` | Turn the backlight off |
-| `QK_BACKLIGHT_UP` | `BL_UP` | Increase the backlight level |
-| `QK_BACKLIGHT_DOWN` | `BL_DOWN` | Decrease the backlight level |
-| `QK_BACKLIGHT_TOGGLE_BREATHING` | `BL_BRTG` | Toggle backlight breathing |
+## Basic Configuration :id=basic-configuration
-## Functions :id=functions
-
-These functions can be used to change the backlighting in custom code:
-
-|Function |Description |
-|------------------------|--------------------------------------------|
-|`backlight_toggle()` |Turn the backlight on or off |
-|`backlight_enable()` |Turn the backlight on |
-|`backlight_disable()` |Turn the backlight off |
-|`backlight_step()` |Cycle through backlight levels |
-|`backlight_increase()` |Increase the backlight level |
-|`backlight_decrease()` |Decrease the backlight level |
-|`backlight_level(x)` |Sets the backlight level to specified level |
-|`get_backlight_level()` |Return the current backlight level |
-|`is_backlight_enabled()`|Return whether the backlight is currently on|
-
-If backlight breathing is enabled (see below), the following functions are also available:
-
-|Function |Description |
-|---------------------|--------------------------------------|
-|`breathing_toggle()` |Turn the backlight breathing on or off|
-|`breathing_enable()` |Turns on backlight breathing |
-|`breathing_disable()`|Turns off backlight breathing |
-
-## Configuration :id=configuration
-
-To select which driver to use, configure your `rules.mk` with the following:
-
-```make
-BACKLIGHT_DRIVER = software
-```
-
-Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help on individual drivers.
-
-To configure the backlighting, `#define` these in your `config.h`:
+Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|------------------|-----------------------------------------------------------------------------------------------------------------|
-|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LED(s) |
+|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LEDs |
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|`BACKLIGHT_CAPS_LOCK` |*Not defined* |Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported |
@@ -76,24 +42,88 @@ To configure the backlighting, `#define` these in your `config.h`:
Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`.
-### Backlight On State :id=backlight-on-state
+### "On" State :id=on-state
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
-This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
+To configure the "on" state of the backlight circuit, add the following to your `config.h`:
+
+```c
+#define BACKLIGHT_ON_STATE 0
+```
+
+### Multiple Backlight Pins :id=multiple-backlight-pins
+
+Most keyboards have only one backlight pin which controls all backlight LEDs (especially if the backlight is connected to a hardware PWM pin).
+The `timer` and `software` drivers allow you to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
+
+This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
+
+To configure multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
+
+```c
+#define BACKLIGHT_PINS { F5, B2 }
+```
+
+## Driver Configuration :id=driver-configuration
+
+Backlight driver selection is configured in `rules.mk`. Valid drivers are `pwm` (default), `timer`, `software`, or `custom`. See below for information on individual drivers.
-### AVR Driver :id=avr-driver
+### PWM Driver :id=pwm-driver
-The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
+This is the default backlight driver, which leverages the hardware PWM output capability of the microcontroller.
```make
BACKLIGHT_DRIVER = pwm
```
-#### Caveats :id=avr-caveats
+### Timer Driver :id=timer-driver
+
+This driver is similar to the PWM driver, but instead of directly configuring the pin to output a PWM signal, an interrupt handler is attached to the timer to turn the pin on and off as appropriate.
+
+```make
+BACKLIGHT_DRIVER = timer
+```
+
+### Software Driver :id=software-driver
+
+In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. However, breathing is not supported, and the backlight can flicker when the keyboard is busy.
+
+```make
+BACKLIGHT_DRIVER = software
+```
+
+### Custom Driver :id=custom-driver
+
+If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using a simple API.
+
+```make
+BACKLIGHT_DRIVER = custom
+```
+
+```c
+void backlight_init_ports(void) {
+ // Optional - runs on startup
+ // Usually you want to configure pins here
+}
+void backlight_set(uint8_t level) {
+ // Optional - runs on level change
+ // Usually you want to respond to the new value
+}
+
+void backlight_task(void) {
+ // Optional - runs periodically
+ // Note that this is called in the main keyboard loop,
+ // so long running actions here can cause performance issues
+}
+```
+
+## AVR Configuration :id=avr-configuration
+
+### PWM Driver :id=avr-pwm-driver
-On AVR boards, QMK automatically decides which driver to use according to the following table:
+The following table describes the supported pins for the PWM driver. Only cells marked with a timer number are capable of hardware PWM output; any others must use the `timer` driver.
|Backlight Pin|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
|-------------|-------------|----------|-------------|-------------|---------|-----------|
@@ -108,113 +138,169 @@ On AVR boards, QMK automatically decides which driver to use according to the fo
|`D4` | | | | |Timer 1 | |
|`D5` | | | | |Timer 1 | |
-All other pins will use timer-assisted software PWM:
+### Timer Driver :id=avr-timer-driver
-|Audio Pin|Audio Timer|Software PWM Timer|
-|---------|-----------|------------------|
-|`C4` |Timer 3 |Timer 1 |
-|`C5` |Timer 3 |Timer 1 |
-|`C6` |Timer 3 |Timer 1 |
-|`B5` |Timer 1 |Timer 3 |
-|`B6` |Timer 1 |Timer 3 |
-|`B7` |Timer 1 |Timer 3 |
+Any GPIO pin can be used with this driver. The following table describes the supported timers:
-When both timers are in use for Audio, the backlight PWM cannot use a hardware timer, and will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
+|AT90USB64/128|AT90USB162|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
+|-------------|----------|-------------|-------------|---------|-----------|
+|Timers 1 & 3 |Timer 1 |Timers 1 & 3 |Timer 1 |Timer 1 |Timer 1 |
-#### Hardware PWM Implementation :id=hardware-pwm-implementation
+The following `#define`s apply only to the `timer` driver:
-When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
-The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
-In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus the brightness, where `0x0000` is completely off and `0xFFFF` is completely on.
+|Define |Default|Description |
+|-----------------------|-------|----------------|
+|`BACKLIGHT_PWM_TIMER` |`1` |The timer to use|
-The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
-In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
+Note that the choice of timer may conflict with the [Audio](feature_audio.md) feature.
-#### Timer Assisted PWM Implementation :id=timer-assisted-implementation
+## ChibiOS/ARM Configuration :id=arm-configuration
-When `BACKLIGHT_PIN` is not set to a hardware backlight pin, QMK will use a hardware timer configured to trigger software interrupts. This time will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
-When resetting to 0, the CPU will fire an OVF (overflow) interrupt that will turn the LEDs on, starting the duty cycle.
-The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the CPU will fire a Compare Output match interrupt, which will turn the LEDs off.
-In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus the brightness, where `0x0000` is completely off and `0xFFFF` is completely on.
+### PWM Driver :id=arm-pwm-driver
-The breathing effect is the same as in the hardware PWM implementation.
+Depending on the ChibiOS board configuration, you may need to enable PWM at the keyboard level. For STM32, this would look like:
-### ARM Driver :id=arm-configuration
+`halconf.h`:
+```c
+#define HAL_USE_PWM TRUE
+```
+`mcuconf.h`:
+```c
+#undef STM32_PWM_USE_TIM4
+#define STM32_PWM_USE_TIM4 TRUE
+```
-While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
+The following `#define`s apply only to the `pwm` driver:
-```make
-BACKLIGHT_DRIVER = pwm
+|Define |Default |Description |
+|-----------------------|--------|-----------------------------------|
+|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use |
+|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
+|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use|
+
+Refer to the ST datasheet for your particular MCU to determine these values. For example, these defaults are set up for pin `B8` on a Proton-C (STM32F303) using `TIM4_CH3` on AF2. Unless you are designing your own keyboard, you generally should not need to change them.
+
+### Timer Driver :id=arm-timer-driver
+
+Depending on the ChibiOS board configuration, you may need to enable general-purpose timers at the keyboard level. For STM32, this would look like:
+
+`halconf.h`:
+```c
+#define HAL_USE_GPT TRUE
+```
+`mcuconf.h`:
+```c
+#undef STM32_GPT_USE_TIM15
+#define STM32_GPT_USE_TIM15 TRUE
```
-#### ChibiOS Configuration :id=arm-configuration
+The following `#define`s apply only to the `timer` driver:
-The following `#define`s apply only to ARM-based keyboards:
+|Define |Default |Description |
+|----------------------|--------|----------------|
+|`BACKLIGHT_GPT_DRIVER`|`GPTD15`|The timer to use|
-|Define |Default|Description |
-|-----------------------|-------|-----------------------------------|
-|`BACKLIGHT_PWM_DRIVER` |`PWMD4`|The PWM driver to use |
-|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
-|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use|
+## Example Schematic
-See the ST datasheet for your particular MCU to determine these values. Unless you are designing your own keyboard, you generally should not need to change them.
+Since the MCU can only supply so much current to its GPIO pins, instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
-#### Caveats :id=arm-caveats
+In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
+A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
+The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
-Currently only hardware PWM is supported, not timer assisted, and does not provide automatic configuration.
+![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)
-### Software PWM Driver :id=software-pwm-driver
+## API :id=api
-In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your `rules.mk`:
+### `void backlight_toggle(void)` :id=api-backlight-toggle
-```make
-BACKLIGHT_DRIVER = software
-```
+Toggle the backlight on or off.
-#### Multiple Backlight Pins :id=multiple-backlight-pins
+---
-Most keyboards have only one backlight pin which controls all backlight LEDs (especially if the backlight is connected to a hardware PWM pin).
-In software PWM, it is possible to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
+### `void backlight_enable(void)` :id=api-backlight-enable
-This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
+Turn the backlight on.
-To activate multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
+---
-```c
-#define BACKLIGHT_PINS { F5, B2 }
-```
+### `void backlight_disable(void)` :id=api-backlight-disable
-### Custom Driver :id=custom-driver
+Turn the backlight off.
-If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using this simple API provided by QMK. To enable, add this to your `rules.mk`:
+---
-```make
-BACKLIGHT_DRIVER = custom
-```
+### `void backlight_step(void)` :id=api-backlight-step
-Then implement any of these hooks:
+Cycle through backlight levels.
-```c
-void backlight_init_ports(void) {
- // Optional - runs on startup
- // Usually you want to configure pins here
-}
-void backlight_set(uint8_t level) {
- // Optional - runs on level change
- // Usually you want to respond to the new value
-}
+---
-void backlight_task(void) {
- // Optional - runs periodically
- // Note that this is called in the main keyboard loop,
- // so long running actions here can cause performance issues
-}
-```
+### `void backlight_increase(void)` :id=api-backlight-increase
-## Example Schematic
+Increase the backlight level.
-In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
-A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
-The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
+---
-![Backlight example circuit](https://i.imgur.com/BmAvoUC.png)
+### `void backlight_decrease(void)` :id=api-backlight-decrease
+
+Decrease the backlight level.
+
+---
+
+### `void backlight_level(uint8_t level)` :id=api-backlight-level
+
+Set the backlight level.
+
+#### Arguments :id=api-backlight-level-arguments
+
+ - `uint8_t level`
+ The level to set, from 0 to `BACKLIGHT_LEVELS`.
+
+---
+
+### `uint8_t get_backlight_level(void)` :id=api-get-backlight-level
+
+Get the current backlight level.
+
+#### Return Value :id=api-get-backlight-level-return
+
+The current backlight level, from 0 to `BACKLIGHT_LEVELS`.
+
+---
+
+### `bool is_backlight_enabled(void)` :id=api-is-backlight-enabled
+
+Get the current backlight state.
+
+#### Return Value :id=api-is-backlight-enabled-return
+
+`true` if the backlight is enabled.
+
+---
+
+### `void backlight_toggle_breathing(void)` :id=api-backlight-toggle-breathing
+
+Toggle backlight breathing on or off.
+
+---
+
+### `void backlight_enable_breathing(void)` :id=api-backlight-enable-breathing
+
+Turn backlight breathing on.
+
+---
+
+### `void backlight_disable_breathing(void)` :id=api-backlight-disable-breathing
+
+Turn backlight breathing off.
+
+---
+
+### `bool is_backlight_breathing(void)` :id=api-is-backlight-breathing
+
+Get the current backlight breathing state.
+
+#### Return Value :id=api-is-backlight-breathing-return
+
+`true` if backlight breathing is enabled.
diff --git a/docs/feature_bluetooth.md b/docs/feature_bluetooth.md
index f7ded84d86..5fac06fba7 100644
--- a/docs/feature_bluetooth.md
+++ b/docs/feature_bluetooth.md
@@ -4,10 +4,10 @@
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
-|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
-|----------------------------------------------------------------|--------------------|---------------|--------------------------------|--------------|
-|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = RN42` |RN-42 |
-|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = BluefruitLE`|nRF51822 |
+|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
+|----------------------------------------------------------------|--------------------|---------------|---------------------------------|--------------|
+|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = rn42` |RN-42 |
+|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = bluefruit_le`|nRF51822 |
Not Supported Yet but possible:
* [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479). [Possible tmk implementation found in](https://github.com/tmk/tmk_keyboard/issues/514)
@@ -32,7 +32,7 @@ Add the following to your `rules.mk`:
```make
BLUETOOTH_ENABLE = yes
-BLUETOOTH_DRIVER = BluefruitLE # or RN42
+BLUETOOTH_DRIVER = bluefruit_le # or rn42
```
## Bluetooth Keycodes
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index b456bad736..68145edd6c 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -4,11 +4,12 @@
The following options are currently available for haptic feedback in `rules.mk`:
-```
+```make
HAPTIC_ENABLE = yes
-HAPTIC_DRIVER += DRV2605L
-HAPTIC_DRIVER += SOLENOID
+HAPTIC_DRIVER = drv2605l
+# or
+HAPTIC_DRIVER = solenoid
```
The following `config.h` settings are available for all types of haptic feedback:
@@ -92,30 +93,30 @@ This driver supports 2 different feedback motors. Set the following in your `con
Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.
-```
-#define FB_ERM_LRA 0
-#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
-#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
+```c
+#define DRV2605L_FB_ERM_LRA 0
+#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
+#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
/* Please refer to your datasheet for the optimal setting for your specific motor. */
-#define RATED_VOLTAGE 3
-#define V_PEAK 5
+#define DRV2605L_RATED_VOLTAGE 3
+#define DRV2605L_V_PEAK 5
```
##### LRA
Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.
-```
-#define FB_ERM_LRA 1
-#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
-#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
+```c
+#define DRV2605L_FB_ERM_LRA 1
+#define DRV2605L_FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
+#define DRV2605L_FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
/* Please refer to your datasheet for the optimal setting for your specific motor. */
-#define RATED_VOLTAGE 2
-#define V_PEAK 2.8
-#define V_RMS 2.0
-#define V_PEAK 2.1
-#define F_LRA 205 /* resonance freq */
+#define DRV2605L_RATED_VOLTAGE 2
+#define DRV2605L_V_PEAK 2.8
+#define DRV2605L_V_RMS 2.0
+#define DRV2605L_V_PEAK 2.1
+#define DRV2605L_F_LRA 205 /* resonance freq */
```
#### DRV2605L waveform library
@@ -170,13 +171,13 @@ List of waveform sequences from the datasheet:
| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
### Optional DRV2605L defines
-```
-#define DRV_GREETING *sequence name or number*
+```c
+#define DRV2605L_GREETING *sequence name or number*
```
If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
-```
-#define DRV_MODE_DEFAULT *sequence name or number*
+```c
+#define DRV2605L_DEFAULT_MODE *sequence name or number*
```
This will set what sequence `HF_RST` will set as the active mode. If not defined, mode will be set to 1 when `HF_RST` is pressed.
diff --git a/docs/feature_hd44780.md b/docs/feature_hd44780.md
index 4ade640baa..dcbd656bbe 100644
--- a/docs/feature_hd44780.md
+++ b/docs/feature_hd44780.md
@@ -1,6 +1,6 @@
-# HD44780 LCD Driver
+# HD44780 LCD Driver :id=hd44780-lcd-driver
-## Supported Hardware
+## Supported Hardware :id=supported-hardware
LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) IC or equivalent, communicating in 4-bit mode.
@@ -11,7 +11,7 @@ LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
To run these modules at 3.3V, an additional MAX660 voltage converter IC must be soldered on, along with two 10µF capacitors. See [this page](https://www.codrey.com/electronic-circuits/hack-your-16x2-lcd/) for more details.
-## Usage
+## Usage :id=usage
Add the following to your `rules.mk`:
@@ -19,7 +19,7 @@ Add the following to your `rules.mk`:
HD44780_ENABLE = yes
```
-## Basic Configuration
+## Basic Configuration :id=basic-configuration
Add the following to your `config.h`:
@@ -33,9 +33,9 @@ Add the following to your `config.h`:
|`HD44780_DISPLAY_LINES`|`2` |The number of visible lines on the display |
|`HD44780_WRAP_LINES` |*Not defined* |If defined, input characters will wrap to the next line |
-## Examples
+## Examples :id=examples
-### Hello World
+### Hello World :id=example-hello-world
Add the following to your `keymap.c`:
@@ -46,7 +46,7 @@ void keyboard_post_init_user(void) {
}
```
-### Custom Character Definition
+### Custom Character Definition :id=example-custom-character
Up to eight custom characters can be defined. This data is stored in the Character Generator RAM (CGRAM), and is not persistent across power cycles.
@@ -77,15 +77,15 @@ void keyboard_post_init_user(void) {
}
```
-## API
+## API :id=api
-### `void hd44780_init(bool cursor, bool blink)`
+### `void hd44780_init(bool cursor, bool blink)` :id=api-hd44780-init
Initialize the display.
This function should be called only once, before any of the other functions can be called.
-#### Arguments
+#### Arguments :id=api-hd44780-init-arguments
- `bool cursor`
Whether to show the cursor.
@@ -94,7 +94,7 @@ This function should be called only once, before any of the other functions can
---
-### `void hd44780_clear(void)`
+### `void hd44780_clear(void)` :id=api-hd44780-clear
Clear the display.
@@ -102,7 +102,7 @@ This function is called on init.
---
-### `void hd44780_home(void)`
+### `void hd44780_home(void)` :id=api-hd44780-home
Move the cursor to the home position.
@@ -110,13 +110,13 @@ This function is called on init.
---
-### `void hd44780_on(bool cursor, bool blink)`
+### `void hd44780_on(bool cursor, bool blink)` :id=api-hd44780-on
Turn the display on, and/or set the cursor properties.
This function is called on init.
-#### Arguments
+#### Arguments :id=api-hd44780-on-arguments
- `bool cursor`
Whether to show the cursor.
@@ -125,17 +125,17 @@ This function is called on init.
---
-### `void hd44780_off(void)`
+### `void hd44780_off(void)` :id=api-hd44780-off
Turn the display off.
---
-### `void hd44780_set_cursor(uint8_t col, uint8_t line)`
+### `void hd44780_set_cursor(uint8_t col, uint8_t line)` :id=api-hd44780-set-cursor
Move the cursor to the specified position on the display.
-#### Arguments
+#### Arguments :id=api-hd44780-set-cursor-arguments
- `uint8_t col`
The column number to move to, from 0 to 15 on 16x2 displays.
@@ -144,48 +144,48 @@ Move the cursor to the specified position on the display.
---
-### `void hd44780_putc(char c)`
+### `void hd44780_putc(char c)` :id=api-hd44780-putc
Print a character to the display. The newline character `\n` will move the cursor to the start of the next line.
The exact character shown may depend on the ROM code of your particular display - refer to the datasheet for the full character set.
-#### Arguments
+#### Arguments :id=api-hd44780-putc-arguments
- `char c`
The character to print.
---
-### `void hd44780_puts(const char *s)`
+### `void hd44780_puts(const char *s)` :id=api-hd44780-puts
Print a string of characters to the display.
-#### Arguments
+#### Arguments :id=api-hd44780-puts-arguments
- `const char *s`
The string to print.
---
-### `void hd44780_puts_P(const char *s)`
+### `void hd44780_puts_P(const char *s)` :id=api-hd44780-puts-p
Print a string of characters from PROGMEM to the display.
On ARM devices, this function is simply an alias of `hd44780_puts()`.
-#### Arguments
+#### Arguments :id=api-hd44780-puts-p-arguments
- `const char *s`
The PROGMEM string to print (ie. `PSTR("Hello")`).
---
-### `void hd44780_define_char(uint8_t index, uint8_t *data)`
+### `void hd44780_define_char(uint8_t index, uint8_t *data)` :id=api-hd44780-define-char
Define a custom character.
-#### Arguments
+#### Arguments :id=api-hd44780-define-char-arguments
- `uint8_t index`
The index of the custom character to define, from 0 to 7.
@@ -194,13 +194,13 @@ Define a custom character.
---
-### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)`
+### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)` :id=api-hd44780-define-char-p
Define a custom character from PROGMEM.
On ARM devices, this function is simply an alias of `hd44780_define_char()`.
-#### Arguments
+#### Arguments :id=api-hd44780-define-char-p-arguments
- `uint8_t index`
The index of the custom character to define, from 0 to 7.
@@ -209,21 +209,21 @@ On ARM devices, this function is simply an alias of `hd44780_define_char()`.
---
-### `bool hd44780_busy(void)`
+### `bool hd44780_busy(void)` :id=api-hd44780-busy
Indicates whether the display is currently processing, and cannot accept instructions.
-#### Return Value
+#### Return Value :id=api-hd44780-busy-arguments
`true` if the display is busy.
---
-### `void hd44780_write(uint8_t data, bool isData)`
+### `void hd44780_write(uint8_t data, bool isData)` :id=api-hd44780-write
Write a byte to the display.
-#### Arguments
+#### Arguments :id=api-hd44780-write-arguments
- `uint8_t data`
The byte to send to the display.
@@ -232,67 +232,67 @@ Write a byte to the display.
---
-### `uint8_t hd44780_read(bool isData)`
+### `uint8_t hd44780_read(bool isData)` :id=api-hd44780-read
Read a byte from the display.
-#### Arguments
+#### Arguments :id=api-hd44780-read-arguments
- `bool isData`
Whether to read the current cursor position, or the character at the cursor.
-#### Return Value
+#### Return Value :id=api-hd44780-read-return
If `isData` is `true`, the returned byte will be the character at the current DDRAM address. Otherwise, it will be the current DDRAM address and the busy flag.
---
-### `void hd44780_command(uint8_t command)`
+### `void hd44780_command(uint8_t command)` :id=api-hd44780-command
Send a command to the display. Refer to the datasheet and `hd44780.h` for the valid commands and defines.
This function waits for the display to clear the busy flag before sending the command.
-#### Arguments
+#### Arguments :id=api-hd44780-command-arguments
- `uint8_t command`
The command to send.
---
-### `void hd44780_data(uint8_t data)`
+### `void hd44780_data(uint8_t data)` :id=api-hd44780-data
Send a byte of data to the display.
This function waits for the display to clear the busy flag before sending the data.
-#### Arguments
+#### Arguments :id=api-hd44780-data-arguments
- `uint8_t data`
The byte of data to send.
---
-### `void hd44780_set_cgram_address(uint8_t address)`
+### `void hd44780_set_cgram_address(uint8_t address)` :id=api-hd44780-set-cgram-address
Set the CGRAM address.
This function is used when defining custom characters.
-#### Arguments
+#### Arguments :id=api-hd44780-set-cgram-address-arguments
- `uint8_t address`
The CGRAM address to move to, from `0x00` to `0x3F`.
---
-### `void hd44780_set_ddram_address(uint8_t address)`
+### `void hd44780_set_ddram_address(uint8_t address)` :id=api-hd44780-set-ddram-address
Set the DDRAM address.
This function is used when printing characters to the display, and setting the cursor.
-#### Arguments
+#### Arguments :id=api-hd44780-set-ddram-address-arguments
- `uint8_t address`
The DDRAM address to move to, from `0x00` to `0x7F`.
diff --git a/docs/feature_key_overrides.md b/docs/feature_key_overrides.md
index 608eb001e4..ec7efd4c01 100644
--- a/docs/feature_key_overrides.md
+++ b/docs/feature_key_overrides.md
@@ -225,3 +225,30 @@ The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT
## Difference to Combos :id=difference-to-combos
Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interacton with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable.
+
+## Solution to the problem of flashing modifiers :id=neutralize-flashing-modifiers
+
+If the programs you use bind an action to taps of modifier keys (e.g. tapping left GUI to bring up the applications menu or tapping left Alt to focus the menu bar), you may find that using key overrides with suppressed mods falsely triggers those actions. To counteract this, you can define a `DUMMY_MOD_NEUTRALIZER_KEYCODE` in `config.h` that will get sent in between the register and unregister events of a suppressed modifier. That way, the programs on your computer will no longer interpret the mod suppression induced by key overrides as a lone tap of a modifier key and will thus not falsely trigger the undesired action.
+
+Naturally, for this technique to be effective, you must choose a `DUMMY_MOD_NEUTRALIZER_KEYCODE` for which no keyboard shortcuts are bound to. Recommended values are: `KC_RIGHT_CTRL` or `KC_F18`.
+Please note that `DUMMY_MOD_NEUTRALIZER_KEYCODE` must be a basic, unmodified, HID keycode so values like `KC_NO`, `KC_TRANSPARENT` or `KC_PIPE` aka `S(KC_BACKSLASH)` are not permitted.
+
+By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your `config.h`:
+
+```c
+#define MODS_TO_NEUTRALIZE { <mod_mask_1>, <mod_mask_2>, ... }
+```
+
+Examples:
+
+```c
+#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL
+
+// Neutralize left alt and left GUI (Default value)
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) }
+
+// Neutralize left alt, left GUI, right GUI and left Control+Shift
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) }
+```
+
+!> Do not use `MOD_xxx` constants like `MOD_LSFT` or `MOD_RALT`, since they're 5-bit packed bit-arrays while `MODS_TO_NEUTRALIZE` expects a list of 8-bit packed bit-arrays. Use `MOD_BIT(<kc>)` or `MOD_MASK_xxx` instead.
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 86dff89eca..dcb87f954c 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -12,7 +12,7 @@ There is basic support for addressable LED matrix lighting with the I2C IS31FL37
```make
LED_MATRIX_ENABLE = yes
-LED_MATRIX_DRIVER = IS31FL3731
+LED_MATRIX_DRIVER = is31fl3731
```
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
@@ -139,7 +139,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
-const is31_led __flash g_is31_leds[LED_MATRIX_LED_COUNT] = {
+const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@@ -158,7 +158,7 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c
-const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
+const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
* LED Index
* | Scaling
* | | */
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index eed4f4f4aa..42448325c9 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -67,6 +67,7 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|`MOUSEKEY_TIME_TO_MAX` |30 |Time until maximum cursor speed is reached |
|`MOUSEKEY_WHEEL_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements |
+|`MOUSEKEY_WHEEL_DELTA` |1 |Wheel movement step size |
|`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached |
@@ -101,7 +102,7 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
Tips:
* The smoothness of the cursor movement depends on the `MOUSEKEY_INTERVAL` setting. The shorter the interval is set the smoother the movement will be. Setting the value too low makes the cursor unresponsive. Lower settings are possible if the micro processor is fast enough. For example: At an interval of `8` milliseconds, `125` movements per second will be initiated. With a base speed of `1000` each movement will move the cursor by `8` pixels.
-* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `2`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
+* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
### Constant mode
diff --git a/docs/feature_rawhid.md b/docs/feature_rawhid.md
index 558a23a80f..094dd21c7e 100644
--- a/docs/feature_rawhid.md
+++ b/docs/feature_rawhid.md
@@ -1,69 +1,156 @@
-# Raw HID
+# Raw HID :id=raw-hid
-Raw HID allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or changing RGB LED colors and modes.
+The Raw HID feature allows for bidirectional communication between QMK and the host computer over an HID interface. This has many potential use cases, such as switching keymaps on the fly or sending useful metrics like CPU/RAM usage.
-There are two main components to getting raw HID working with your keyboard.
+In order to communicate with the keyboard using this feature, you will need to write a program that runs on the host. As such, some basic programming skills are required - more if you intend to implement complex behaviour.
-## Keyboard firmware
+## Usage :id=usage
-The implementation is fairly straightforward for the firmware.
-In your `rules.mk` add:
+Add the following to your `rules.mk`:
```make
RAW_ENABLE = yes
```
-In your `keymap.c` include `"raw_hid.h"` and implement the following:
+## Basic Configuration :id=basic-configuration
+
+By default, the HID Usage Page and Usage ID for the Raw HID interface are `0xFF60` and `0x61`. However, they can be changed if necessary by adding the following to your `config.h`:
+
+|Define |Default |Description |
+|----------------|--------|---------------------------------------|
+|`RAW_USAGE_PAGE`|`0xFF60`|The usage page of the Raw HID interface|
+|`RAW_USAGE_ID` |`0x61` |The usage ID of the Raw HID interface |
+
+## Sending Data to the Keyboard :id=sending-data-to-the-keyboard
+
+To send data to the keyboard, you must first find a library for communicating with HID devices in the programming language of your choice. Here are some examples:
+
+* **Node.js:** [node-hid](https://github.com/node-hid/node-hid)
+* **C/C++:** [hidapi](https://github.com/libusb/hidapi)
+* **Java:** [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java)
+* **Python:** [pyhidapi](https://pypi.org/project/hid/)
+
+Please refer to these libraries' own documentation for instructions on usage. Remember to close the device once you are finished with it!
+
+Next, you will need to know the USB Vendor and Product IDs of the device. These can easily be found by looking at your keyboard's `info.json`, under the `usb` object (alternatively, you can also use Device Manager on Windows, System Information on macOS, or `lsusb` on Linux). For example, the Vendor ID for the Planck Rev 6 is `0x03A8`, and the Product ID is `0xA4F9`.
+
+It's also a good idea to narrow down the list of potential HID devices the library may give you by filtering on the usage page and usage ID, to avoid accidentally opening the interface on the same device for the keyboard, or mouse, or media keys, etc.
+
+Once you are able to open the HID device and send reports to it, it's time to handle them on the keyboard side. Implement the following function in your `keymap.c` and start coding:
```c
void raw_hid_receive(uint8_t *data, uint8_t length) {
- // Your code goes here. data is the packet received from host.
+ // Your code goes here
+ // `data` is a pointer to the buffer containing the received HID report
+ // `length` is the length of the report - always `RAW_EPSIZE`
}
```
-The `"raw_hid.h"` header also declares `void raw_hid_send(uint8_t *data, uint8_t length);` which allows sending packets from keyboard to host. As an example, it can also be used for debugging when building your host application by returning all data back to the host.
+!> Because the HID specification does not support variable length reports, all reports in both directions must be exactly `RAW_EPSIZE` (currently 32) bytes long, regardless of actual payload length. However, variable length payloads can potentially be implemented on top of this by creating your own data structure that may span multiple reports.
+
+## Receiving Data from the Keyboard :id=receiving-data-from-the-keyboard
+
+If you need the keyboard to send data back to the host, simply call the `raw_hid_send()` function. It requires two arguments - a pointer to a 32-byte buffer containing the data you wish to send, and the length (which should always be `RAW_EPSIZE`).
+
+The received report can then be handled in whichever way your HID library provides.
+
+## Simple Example :id=simple-example
+
+The following example reads the first byte of the received report from the host, and if it is an ASCII "A", responds with "B". `memset()` is used to fill the response buffer (which could still contain the previous response) with null bytes.
```c
void raw_hid_receive(uint8_t *data, uint8_t length) {
- raw_hid_send(data, length);
+ uint8_t response[length];
+ memset(response, 0, length);
+ response[0] = 'B';
+
+ if(data[0] == 'A') {
+ raw_hid_send(response, length);
+ }
}
```
-These two functions send and receive packets of length `RAW_EPSIZE` bytes to and from the host (32 on LUFA/ChibiOS/V-USB, 64 on ATSAM).
+On the host side (here we are using Python and the `pyhidapi` library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent.
+
+For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed.
+
+```python
+import sys
+import hid
+
+vendor_id = 0x4335
+product_id = 0x0002
+
+usage_page = 0xFF60
+usage = 0x61
+report_length = 32
+
+def get_raw_hid_interface():
+ device_interfaces = hid.enumerate(vendor_id, product_id)
+ raw_hid_interfaces = [i for i in device_interfaces if i['usage_page'] == usage_page and i['usage'] == usage]
+
+ if len(raw_hid_interfaces) == 0:
+ return None
-Make sure to flash raw enabled firmware before proceeding with working on the host side.
+ interface = hid.Device(path=raw_hid_interfaces[0]['path'])
-## Host (Windows/macOS/Linux)
+ print(f"Manufacturer: {interface.manufacturer}")
+ print(f"Product: {interface.product}")
-This is the more complicated part as it will require some digging.
+ return interface
-To connect your host computer to your keyboard with raw HID you need four pieces of information about your keyboard:
+def send_raw_report(data):
+ interface = get_raw_hid_interface()
-1. Vendor ID
-2. Product ID
-3. Usage Page
-4. Usage
+ if interface is None:
+ print("No device found")
+ sys.exit(1)
+
+ request_data = [0x00] * (report_length + 1) # First byte is Report ID
+ request_data[1:len(data) + 1] = data
+ request_report = bytes(request_data)
+
+ print("Request:")
+ print(request_report)
+
+ try:
+ interface.write(request_report)
+
+ response_report = interface.read(report_length, timeout=1000)
+
+ print("Response:")
+ print(response_report)
+ finally:
+ interface.close()
+
+if __name__ == '__main__':
+ send_raw_report([
+ 0x41
+ ])
+```
-The first two can easily be found in your keyboard's `config.h` in the keyboard's main directory under `VENDOR_ID` and `PRODUCT_ID`.
+## API :id=api
-The final two can be overridden in your keyboard's `config.h` in the keyboard's main directory by redefining the values: `#define RAW_USAGE_PAGE 0xFF60` and `#define RAW_USAGE_ID 0x61`.
+### `void raw_hid_receive(uint8_t *data, uint8_t length)` :id=api-raw-hid-receive
-By default, **Usage Page** is `0xFF60` and **Usage** is `0x61`.
+Callback, invoked when a raw HID report has been received from the host.
-### Building your host
+#### Arguments :id=api-raw-hid-receive-arguments
-You can build your host using any language that has an available HID implementation library if you don't wish to make your own. The ones we know of for popular languages are:
+ - `uint8_t *data`
+ A pointer to the received data. Always 32 bytes in length.
+ - `uint8_t length`
+ The length of the buffer. Always 32.
-* Node: [node-hid](https://github.com/node-hid/node-hid).
-* C: [hidapi](https://github.com/libusb/hidapi).
-* Java: [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java).
-* Python: [pyhidapi](https://pypi.org/project/hid/).
+---
-This is not an exhaustive cross-platform list but should get you started. There are no special requirements for using raw HID so any HID library should work.
+### `void raw_hid_send(uint8_t *data, uint8_t length)` :id=api-raw-hid-send
-Now that you have all four pieces of information required to open HID interface to your keyboard. All you need to do is use your library's available functions to open the device with its ID parameters.
+Send an HID report.
-Note that Vendor ID and Product ID are not actually required to open the device. They are used only to filter to a specific device out of the many HID devices you have plugged in. Many libraries will give you the option to open the device using Product Name or Manufacturer Name instead, `node-hid` being a prime example. This will create issues for devices with builtin USB Hub or any extra HID interfaces where you will have multiple interfaces with the same name or from the same manufacturer. The Vendor ID together with Product ID create a unique designation to a single interface and will not exhibit this problem. Therefore, even if your library doesn't require you to, it is best to use them to avoid issues.
-Unlike Vendor ID and Product ID though, Usage Page and Usage are necessary for successful communication.
+#### Arguments :id=api-raw-hid-send-arguments
-It should go without saying that regardless of the library you're using, you should always make sure to close the interface when finished. Depending on the operating system and your particular environment there may be issues connecting to it again afterwards with another client or another instance of the same client if it's not explicitly closed.
+ - `uint8_t *data`
+ A pointer to the data to send. Must always be 32 bytes in length.
+ - `uint8_t length`
+ The length of the buffer. Must always be 32.
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index 822bc8f734..f92824c122 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -386,7 +386,7 @@ Currently only 4 drivers are supported, but it would be trivial to support for m
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
-const is31_led __flash g_is31_leds[RGB_MATRIX_LED_COUNT] = {
+const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -406,7 +406,7 @@ Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c
-const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
+const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
* LED Index
* | R scaling
* | | G scaling
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index 948bbb241e..fef856f7df 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -524,37 +524,6 @@ By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED
```
<img src="https://user-images.githubusercontent.com/2170248/55743725-08ad7a80-5a6e-11e9-83ed-126a2b0209fc.JPG" alt="simple mapped" width="50%"/>
-For keyboards that use the RGB LEDs as a backlight for each key, you can also define it as in the example below.
-
-```c
-// config.h
-
-#define RGBLED_NUM 30
-
-/* RGB LED Conversion macro from physical array to electric array */
-#define LED_LAYOUT( \
- L00, L01, L02, L03, L04, L05, \
- L10, L11, L12, L13, L14, L15, \
- L20, L21, L22, L23, L24, L25, \
- L30, L31, L32, L33, L34, L35, \
- L40, L41, L42, L43, L44, L45 ) \
- { \
- L05, L04, L03, L02, L01, L00, \
- L10, L11, L12, L13, L14, L15, \
- L25, L24, L23, L22, L21, L20, \
- L30, L31, L32, L33, L34, L35, \
- L46, L45, L44, L43, L42, L41 \
- }
-
-/* RGB LED logical order map */
-/* Top->Bottom, Right->Left */
-#define RGBLIGHT_LED_MAP LED_LAYOUT( \
- 25, 20, 15, 10, 5, 0, \
- 26, 21, 16, 11, 6, 1, \
- 27, 22, 17, 12, 7, 2, \
- 28, 23, 18, 13, 8, 3, \
- 29, 24, 19, 14, 9, 4 )
-
```
## Clipping Range
diff --git a/docs/feature_send_string.md b/docs/feature_send_string.md
index 67df0224e9..7d3f3ba32a 100644
--- a/docs/feature_send_string.md
+++ b/docs/feature_send_string.md
@@ -1,4 +1,4 @@
-# Send String
+# Send String :id=send-string
The Send String API is part of QMK's macro system. It allows for sequences of keystrokes to be sent automatically.
@@ -6,7 +6,7 @@ The full ASCII character set is supported, along with all of the keycodes in the
?> Unicode characters are **not** supported with this API -- see the [Unicode](feature_unicode.md) feature instead.
-## Usage
+## Usage :id=usage
Send String is enabled by default, so there is usually no need for any special setup. However, if it is disabled, add the following to your `rules.mk`:
@@ -14,7 +14,7 @@ Send String is enabled by default, so there is usually no need for any special s
SEND_STRING_ENABLE = yes
```
-## Basic Configuration
+## Basic Configuration :id=basic-configuration
Add the following to your `config.h`:
@@ -23,7 +23,7 @@ Add the following to your `config.h`:
|`SENDSTRING_BELL`|*Not defined* |If the [Audio](feature_audio.md) feature is enabled, the `\a` character (ASCII `BEL`) will beep the speaker.|
|`BELL_SOUND` |`TERMINAL_SOUND`|The song to play when the `\a` character is encountered. By default, this is an eighth note of C5. |
-## Keycodes
+## Keycodes :id=keycodes
The Send String functions accept C string literals, but specific keycodes can be injected with the below macros. All of the keycodes in the [Basic Keycode range](keycodes_basic.md) are supported (as these are the only ones that will actually be sent to the host), but with an `X_` prefix instead of `KC_`.
@@ -44,13 +44,13 @@ The following characters are also mapped to their respective keycodes for conven
|`\t` |`\x1B`|`TAB`|`KC_TAB` |
| |`\x7F`|`DEL`|`KC_DELETE` |
-### Language Support
+### Language Support :id=language-support
By default, Send String assumes your OS keyboard layout is set to US ANSI. If you are using a different keyboard layout, you can [override the lookup tables used to convert ASCII characters to keystrokes](reference_keymap_extras.md#sendstring-support).
-## Examples
+## Examples :id=examples
-### Hello World
+### Hello World :id=example-hello-world
A simple custom keycode which types out "Hello, world!" and the Enter key when pressed.
@@ -70,7 +70,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
```
-### Keycode Injection
+### Keycode Injection :id=example-keycode-injection
This example types out opening and closing curly braces, then taps the left arrow key to move the cursor between the two.
@@ -84,26 +84,26 @@ This example types Ctrl+A, then Ctrl+C, without releasing Ctrl.
SEND_STRING(SS_LCTL("ac"));
```
-## API
+## API :id=api
-### `void send_string(const char *string)`
+### `void send_string(const char *string)` :id=api-send-string
Type out a string of ASCII characters.
This function simply calls `send_string_with_delay(string, 0)`.
-#### Arguments
+#### Arguments :id=api-send-string-arguments
- `const char *string`
The string to type out.
---
-### `void send_string_with_delay(const char *string, uint8_t interval)`
+### `void send_string_with_delay(const char *string, uint8_t interval)` :id=api-send-string-with-delay
Type out a string of ASCII characters, with a delay between each character.
-#### Arguments
+#### Arguments :id=api-send-string-with-delay-arguments
- `const char *string`
The string to type out.
@@ -112,26 +112,26 @@ Type out a string of ASCII characters, with a delay between each character.
---
-### `void send_string_P(const char *string)`
+### `void send_string_P(const char *string)` :id=api-send-string-p
Type out a PROGMEM string of ASCII characters.
On ARM devices, this function is simply an alias for `send_string_with_delay(string, 0)`.
-#### Arguments
+#### Arguments :id=api-send-string-p-arguments
- `const char *string`
The string to type out.
---
-### `void send_string_with_delay_P(const char *string, uint8_t interval)`
+### `void send_string_with_delay_P(const char *string, uint8_t interval)` :id=api-send-string-with-delay-p
Type out a PROGMEM string of ASCII characters, with a delay between each character.
On ARM devices, this function is simply an alias for `send_string_with_delay(string, interval)`.
-#### Arguments
+#### Arguments :id=api-send-string-with-delay-p-arguments
- `const char *string`
The string to type out.
@@ -140,76 +140,76 @@ On ARM devices, this function is simply an alias for `send_string_with_delay(str
---
-### `void send_char(char ascii_code)`
+### `void send_char(char ascii_code)` :id=api-send-char
Type out an ASCII character.
-#### Arguments
+#### Arguments :id=api-send-char-arguments
- `char ascii_code`
The character to type.
---
-### `void send_dword(uint32_t number)`
+### `void send_dword(uint32_t number)` :id=api-send-dword
Type out an eight digit (unsigned 32-bit) hexadecimal value.
The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`.
-#### Arguments
+#### Arguments :id=api-send-dword-arguments
- `uint32_t number`
The value to type, from 0 to 4,294,967,295.
---
-### `void send_word(uint16_t number)`
+### `void send_word(uint16_t number)` :id=api-send-word
Type out a four digit (unsigned 16-bit) hexadecimal value.
The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`.
-#### Arguments
+#### Arguments :id=api-send-word-arguments
- `uint16_t number`
The value to type, from 0 to 65,535.
---
-### `void send_byte(uint8_t number)`
+### `void send_byte(uint8_t number)` :id=api-send-bytes
Type out a two digit (8-bit) hexadecimal value.
The format is `[0-9a-f]{2}`, eg. `00` through `ff`.
-#### Arguments
+#### Arguments :id=api-send-byte-arguments
- `uint8_t number`
The value to type, from 0 to 255.
---
-### `void send_nibble(uint8_t number)`
+### `void send_nibble(uint8_t number)` :id=api-send-nibble
Type out a single hexadecimal digit.
The format is `[0-9a-f]{1}`, eg. `0` through `f`.
-#### Arguments
+#### Arguments :id=api-send-nibble-arguments
- `uint8_t number`
The value to type, from 0 to 15.
---
-### `void tap_random_base64(void)`
+### `void tap_random_base64(void)` :id=api-tap-random-base64
Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`.
---
-### `SEND_STRING(string)`
+### `SEND_STRING(string)` :id=api-send-string-macro
Shortcut macro for `send_string_with_delay_P(PSTR(string), 0)`.
@@ -217,7 +217,7 @@ On ARM devices, this define evaluates to `send_string_with_delay(string, 0)`.
---
-### `SEND_STRING_DELAY(string, interval)`
+### `SEND_STRING_DELAY(string, interval)` :id=api-send-string-delay-macro
Shortcut macro for `send_string_with_delay_P(PSTR(string), interval)`.
diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md
index b7d8a5528f..42ea233962 100644
--- a/docs/feature_tap_dance.md
+++ b/docs/feature_tap_dance.md
@@ -28,7 +28,7 @@ After this, you'll want to use the `tap_dance_actions` array to specify what act
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode).
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
-
+* `ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(on_each_tap_fn, on_each_release_fn, on_dance_finished_fn, on_dance_reset_fn)`: This macro is identical to `ACTION_TAP_DANCE_FN_ADVANCED` with the addition of `on_each_release_fn` which is invoked every time the key for the tap dance is released. It is worth noting that `on_each_release_fn` will still be called even when the key is released after the dance finishes (e.g. if the key is released after being pressed and held for longer than the `TAPPING_TERM`).
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md
index 455596dab5..312a033257 100644
--- a/docs/feature_unicode.md
+++ b/docs/feature_unicode.md
@@ -42,7 +42,7 @@ Add the following to your `rules.mk`:
UNICODEMAP_ENABLE = yes
```
-Then add `X(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name.
+Then add `UM(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name.
```c
enum unicode_names {
@@ -58,13 +58,13 @@ const uint32_t unicode_map[] PROGMEM = {
};
```
-Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
+Then you can use `UM(BANG)`, `UM(SNEK)` etc. in your keymap.
#### Lower and Upper Case
-Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
+Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `UP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
-This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP()`. This helps blend Unicode keys in with regular alphas.
+This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `UP()`. This helps blend Unicode keys in with regular alphas.
Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L36) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
diff --git a/docs/flashing.md b/docs/flashing.md
index 443fa3123e..113d90ca38 100644
--- a/docs/flashing.md
+++ b/docs/flashing.md
@@ -322,6 +322,29 @@ Flashing sequence:
3. Flash a .bin file
4. Reset the device into application mode (may be done automatically)
+## WB32 DFU
+
+Some keyboards produced for several commercial brands (GMMK, Akko, MonsGeek, Inland) use this bootloader. The `wb32-dfu-updater` utility is bundled with [QMK MSYS](https://msys.qmk.fm/) and [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide). If neither of these flashing methods is available for your OS, you will likely need to [compile the CLI version from source](https://github.com/WestberryTech/wb32-dfu-updater).
+
+The `info.json` setting for this bootloader is `wb32-dfu`.
+
+Compatible flashers:
+
+* [Glorious's build of QMK Toolbox](https://www.gloriousgaming.com/blogs/guides-resources/gmmk-2-qmk-installation-guide) (recommended GUI)
+* [wb32-dfu-updater_cli](https://github.com/WestberryTech/wb32-dfu-updater) / `:flash` target in QMK (recommended command line)
+ ```
+ wb32-dfu-updater_cli -t -s 0x8000000 -D <filename>
+ ```
+
+Flashing sequence:
+
+1. Enter the bootloader using any of the following methods:
+ * Tap the `QK_BOOT` keycode
+ * Press the `RESET` button on the PCB
+2. Wait for the OS to detect the device
+3. Flash a .bin file
+4. Reset the device into application mode (may be done automatically)
+
## tinyuf2
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.
diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md
index 1a7e276098..3d98e4602b 100644
--- a/docs/getting_started_make_guide.md
+++ b/docs/getting_started_make_guide.md
@@ -109,7 +109,7 @@ This allows you to send Unicode characters using `UC(<code point>)` in your keym
`UNICODEMAP_ENABLE`
-This allows you to send Unicode characters using `X(<map index>)` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
+This allows you to send Unicode characters using `UM(<map index>)` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
`UCIS_ENABLE`
diff --git a/docs/i2c_driver.md b/docs/i2c_driver.md
index f4e6c6619e..92b666b5e3 100644
--- a/docs/i2c_driver.md
+++ b/docs/i2c_driver.md
@@ -72,7 +72,7 @@ Configuration-wise, you'll need to set up the peripheral as per your MCU's datas
The following configuration values depend on the specific MCU in use.
-### I2Cv1 :id=i2cv1
+### I2Cv1 :id=arm-configuration-i2cv1
* STM32F1xx
* STM32F2xx
@@ -88,7 +88,7 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#7_I2Cv1_con
|`I2C1_CLOCK_SPEED` |`100000` |
|`I2C1_DUTY_CYCLE` |`STD_DUTY_CYCLE`|
-### I2Cv2 :id=i2cv2
+### I2Cv2 :id=arm-configuration-i2cv2
* STM32F0xx
* STM32F3xx
@@ -105,9 +105,9 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#8_I2Cv2_I2C
|`I2C1_TIMINGR_SCLH` |`38U` |
|`I2C1_TIMINGR_SCLL` |`129U` |
-## Functions :id=functions
+## API :id=api
-### `void i2c_init(void)`
+### `void i2c_init(void)` :id=api-i2c-init
Initialize the I2C driver. This function must be called only once, before any of the below functions can be called.
@@ -126,28 +126,28 @@ void i2c_init(void) {
---
-### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)`
+### `i2c_status_t i2c_start(uint8_t address, uint16_t timeout)` :id=api-i2c-start
Start an I2C transaction.
-#### Arguments
+#### Arguments :id=api-i2c-start-arguments
- `uint8_t address`
The 7-bit I2C address of the device (ie. without the read/write bit - this will be set automatically).
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-start-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)`
+### `i2c_status_t i2c_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)` :id=api-i2c-transmit
Send multiple bytes to the selected I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-transmit-arguments
- `uint8_t address`
The 7-bit I2C address of the device.
@@ -158,17 +158,17 @@ Send multiple bytes to the selected I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-transmit-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)`
+### `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-receive
Receive multiple bytes from the selected I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-receive-arguments
- `uint8_t address`
The 7-bit I2C address of the device.
@@ -179,17 +179,17 @@ Receive multiple bytes from the selected I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-receive-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
+### `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-writereg
Writes to a register with an 8-bit address on the I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-writereg-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
@@ -202,17 +202,17 @@ Writes to a register with an 8-bit address on the I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-writereg-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
+### `i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-writereg16
Writes to a register with a 16-bit address (big endian) on the I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-writereg16-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
@@ -225,17 +225,17 @@ Writes to a register with a 16-bit address (big endian) on the I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-writereg16-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)`
+### `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)` :id=api-i2c-readreg
Reads from a register with an 8-bit address on the I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-readreg-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
@@ -246,7 +246,7 @@ Reads from a register with an 8-bit address on the I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-readreg-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
@@ -256,7 +256,7 @@ Reads from a register with an 8-bit address on the I2C device.
Reads from a register with a 16-bit address (big endian) on the I2C device.
-#### Arguments
+#### Arguments :id=api-i2c-readreg16-arguments
- `uint8_t devaddr`
The 7-bit I2C address of the device.
@@ -267,12 +267,12 @@ Reads from a register with a 16-bit address (big endian) on the I2C device.
- `uint16_t timeout`
The time in milliseconds to wait for a response from the target device.
-#### Return Value
+#### Return Value :id=api-i2c-readreg16-return
`I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
---
-### `i2c_status_t i2c_stop(void)`
+### `i2c_status_t i2c_stop(void)` :id=api-i2c-stop
Stop the current I2C transaction.
diff --git a/docs/ja/data_driven_config.md b/docs/ja/data_driven_config.md
index bc8f4d24a5..6296173b66 100644
--- a/docs/ja/data_driven_config.md
+++ b/docs/ja/data_driven_config.md
@@ -109,8 +109,8 @@ QMK が完全な `info.json` を生成するときはいつでも、`config.h`
パズルの最後のピースは、ビルドシステムに新しいオプションを提供することです。
これは、2つのファイルを生成することによって行われます。
-* `.build/obj_<keyboard>/src/info_config.h`
-* `.build/obj_<keyboard>/src/rules.mk`
+* `.build/obj_<keyboard>_<keymap>/src/info_config.h`
+* `.build/obj_<keyboard>_<keymap>/src/rules.mk`
この2つのファイルは、次のコードによって生成されます。
diff --git a/docs/keycodes.md b/docs/keycodes.md
index e5b6246af7..65762234a4 100644
--- a/docs/keycodes.md
+++ b/docs/keycodes.md
@@ -848,8 +848,8 @@ See also: [Unicode Support](feature_unicode.md)
|Key |Aliases |Description |
|----------------------------|---------|----------------------------------------------------------------|
|`UC(c)` | |Send Unicode code point `c`, up to `0x7FFF` |
-|`X(i)` | |Send Unicode code point at index `i` in `unicode_map` |
-|`XP(i, j)` | |Send Unicode code point at index `i`, or `j` if Shift/Caps is on|
+|`UM(i)` | |Send Unicode code point at index `i` in `unicode_map` |
+|`UP(i, j)` | |Send Unicode code point at index `i`, or `j` if Shift/Caps is on|
|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Cycle through selected input modes |
|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Cycle through selected input modes in reverse |
|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |Switch to macOS input |
diff --git a/docs/spi_driver.md b/docs/spi_driver.md
index a27a3a13d0..c1c6831e73 100644
--- a/docs/spi_driver.md
+++ b/docs/spi_driver.md
@@ -1,8 +1,8 @@
-# SPI Master Driver
+# SPI Master Driver :id=spi-master-driver
The SPI Master drivers used in QMK have a set of common functions to allow portability between MCUs.
-## AVR Configuration
+## AVR Configuration :id=avr-configuration
No special setup is required - just connect the `SS`, `SCK`, `MOSI` and `MISO` pins of your SPI devices to the matching pins on the MCU:
@@ -16,7 +16,7 @@ No special setup is required - just connect the `SS`, `SCK`, `MOSI` and `MISO` p
You may use more than one slave select pin, not just the `SS` pin. This is useful when you have multiple devices connected and need to communicate with them individually.
`SPI_SS_PIN` can be passed to `spi_start()` to refer to `SS`.
-## ChibiOS/ARM Configuration
+## ChibiOS/ARM Configuration :id=arm-configuration
You'll need to determine which pins can be used for SPI -- as an example, STM32 parts generally have multiple SPI peripherals, labeled SPI1, SPI2, SPI3 etc.
@@ -49,19 +49,19 @@ Configuration-wise, you'll need to set up the peripheral as per your MCU's datas
As per the AVR configuration, you may choose any other standard GPIO as a slave select pin, which should be supplied to `spi_start()`.
-## Functions
+## API :id=api
-### `void spi_init(void)`
+### `void spi_init(void)` :id=api-spi-init
Initialize the SPI driver. This function must be called only once, before any of the below functions can be called.
---
-### `bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor)`
+### `bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor)` :id=api-spi-start
Start an SPI transaction.
-#### Arguments
+#### Arguments :id=api-spi-start-arguments
- `pin_t slavePin`
The QMK pin to assert as the slave select pin, eg. `B4`.
@@ -80,71 +80,71 @@ Start an SPI transaction.
- `uint16_t divisor`
The SPI clock divisor, will be rounded up to the nearest power of two. This number can be calculated by dividing the MCU's clock speed by the desired SPI clock speed. For example, an MCU running at 8 MHz wanting to talk to an SPI device at 4 MHz would set the divisor to `2`.
-#### Return Value
+#### Return Value :id=api-spi-start-return
`false` if the supplied parameters are invalid or the SPI peripheral is already in use, or `true`.
---
-### `spi_status_t spi_write(uint8_t data)`
+### `spi_status_t spi_write(uint8_t data)` :id=api-spi-write
Write a byte to the selected SPI device.
-#### Arguments
+#### Arguments :id=api-spi-write-arguments
- `uint8_t data`
The byte to write.
-#### Return Value
+#### Return Value :id=api-spi-write-return
`SPI_STATUS_TIMEOUT` if the timeout period elapses, or `SPI_STATUS_SUCCESS`.
---
-### `spi_status_t spi_read(void)`
+### `spi_status_t spi_read(void)` :id=api-spi-read
Read a byte from the selected SPI device.
-#### Return Value
+#### Return Value :id=api-spi-read-return
`SPI_STATUS_TIMEOUT` if the timeout period elapses, or the byte read from the device.
---
-### `spi_status_t spi_transmit(const uint8_t *data, uint16_t length)`
+### `spi_status_t spi_transmit(const uint8_t *data, uint16_t length)` :id=api-spi-transmit
Send multiple bytes to the selected SPI device.
-#### Arguments
+#### Arguments :id=api-spi-transmit-arguments
- `const uint8_t *data`
A pointer to the data to write from.
- `uint16_t length`
The number of bytes to write. Take care not to overrun the length of `data`.
-#### Return Value
+#### Return Value :id=api-spi-transmit-return
`SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`.
---
-### `spi_status_t spi_receive(uint8_t *data, uint16_t length)`
+### `spi_status_t spi_receive(uint8_t *data, uint16_t length)` :id=api-spi-receive
Receive multiple bytes from the selected SPI device.
-#### Arguments
+#### Arguments :id=api-spi-receive-arguments
- `uint8_t *data`
A pointer to the buffer to read into.
- `uint16_t length`
The number of bytes to read. Take care not to overrun the length of `data`.
-#### Return Value
+#### Return Value :id=api-spi-receive-return
`SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`.
---
-### `void spi_stop(void)`
+### `void spi_stop(void)` :id=api-spi-stop
End the current SPI transaction. This will deassert the slave select pin and reset the endianness, mode and divisor configured by `spi_start()`.
diff --git a/docs/tap_hold.md b/docs/tap_hold.md
index c50acdb84d..094a10753a 100644
--- a/docs/tap_hold.md
+++ b/docs/tap_hold.md
@@ -460,6 +460,31 @@ bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
}
```
+If the programs you use bind an action to taps of modifier keys (e.g. tapping left GUI to bring up the applications menu or tapping left Alt to focus the menu bar), you may find that using retro-tapping falsely triggers those actions. To counteract this, you can define a `DUMMY_MOD_NEUTRALIZER_KEYCODE` in `config.h` that will get sent in between the register and unregister events of a held mod-tap key. That way, the programs on your computer will no longer interpret the mod suppression induced by retro-tapping as a lone tap of a modifier key and will thus not falsely trigger the undesired action.
+
+Naturally, for this technique to be effective, you must choose a `DUMMY_MOD_NEUTRALIZER_KEYCODE` for which no keyboard shortcuts are bound to. Recommended values are: `KC_RIGHT_CTRL` or `KC_F18`.
+Please note that `DUMMY_MOD_NEUTRALIZER_KEYCODE` must be a basic, unmodified, HID keycode so values like `KC_NO`, `KC_TRANSPARENT` or `KC_PIPE` aka `S(KC_BACKSLASH)` are not permitted.
+
+By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your `config.h`:
+
+```c
+#define MODS_TO_NEUTRALIZE { <mod_mask_1>, <mod_mask_2>, ... }
+```
+
+Examples:
+
+```c
+#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL
+
+// Neutralize left alt and left GUI (Default value)
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) }
+
+// Neutralize left alt, left GUI, right GUI and left Control+Shift
+#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) }
+```
+
+!> Do not use `MOD_xxx` constants like `MOD_LSFT` or `MOD_RALT`, since they're 5-bit packed bit-arrays while `MODS_TO_NEUTRALIZE` expects a list of 8-bit packed bit-arrays. Use `MOD_BIT(<kc>)` or `MOD_MASK_xxx` instead.
+
### Retro Shift
[Auto Shift,](feature_auto_shift.md) has its own version of `retro tapping` called `retro shift`. It is extremely similar to `retro tapping`, but holding the key past `AUTO_SHIFT_TIMEOUT` results in the value it sends being shifted. Other configurations also affect it differently; see [here](feature_auto_shift.md#retro-shift) for more information.
diff --git a/docs/uart_driver.md b/docs/uart_driver.md
index 340b648189..a44f2c28d9 100644
--- a/docs/uart_driver.md
+++ b/docs/uart_driver.md
@@ -1,10 +1,10 @@
-# UART Driver
+# UART Driver :id=uart-driver
The UART drivers used in QMK have a set of common functions to allow portability between MCUs.
Currently, this driver does not support enabling hardware flow control (the `RTS` and `CTS` pins) if available, but may do so in future.
-## AVR Configuration
+## AVR Configuration :id=avr-configuration
No special setup is required - just connect the `RX` and `TX` pins of your UART device to the opposite pins on the MCU:
@@ -16,7 +16,7 @@ No special setup is required - just connect the `RX` and `TX` pins of your UART
|ATmega32A |`D1`|`D0`|*n/a*|*n/a*|
|ATmega328/P |`D1`|`D0`|*n/a*|*n/a*|
-## ChibiOS/ARM Configuration
+## ChibiOS/ARM Configuration :id=arm-configuration
You'll need to determine which pins can be used for UART -- as an example, STM32 parts generally have multiple UART peripherals, labeled USART1, USART2, USART3 etc.
@@ -47,45 +47,45 @@ Configuration-wise, you'll need to set up the peripheral as per your MCU's datas
|`#define SD1_RTS_PIN` |The pin to use for RTS |`A12` |
|`#define SD1_RTS_PAL_MODE`|The alternate function mode for RTS |`7` |
-## Functions
+## API :id=api
-### `void uart_init(uint32_t baud)`
+### `void uart_init(uint32_t baud)` :id=api-uart-init
Initialize the UART driver. This function must be called only once, before any of the below functions can be called.
-#### Arguments
+#### Arguments :id=api-uart-init-arguments
- `uint32_t baud`
The baud rate to transmit and receive at. This may depend on the device you are communicating with. Common values are 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200.
---
-### `void uart_write(uint8_t data)`
+### `void uart_write(uint8_t data)` :id=api-uart-write
Transmit a single byte.
-#### Arguments
+#### Arguments :id=api-uart-write-arguments
- `uint8_t data`
The byte to write.
---
-### `uint8_t uart_read(void)`
+### `uint8_t uart_read(void)` :id=api-uart-read
Receive a single byte.
-#### Return Value
+#### Return Value :id=api-uart-read-return
The byte read from the receive buffer. This function will block if the buffer is empty (ie. no data to read).
---
-### `void uart_transmit(const uint8_t *data, uint16_t length)`
+### `void uart_transmit(const uint8_t *data, uint16_t length)` :id=api-uart-transmit
Transmit multiple bytes.
-#### Arguments
+#### Arguments :id=api-uart-transmit-arguments
- `const uint8_t *data`
A pointer to the data to write from.
@@ -94,11 +94,11 @@ Transmit multiple bytes.
---
-### `void uart_receive(char *data, uint16_t length)`
+### `void uart_receive(char *data, uint16_t length)` :id=api-uart-receive
Receive multiple bytes.
-#### Arguments
+#### Arguments :id=api-uart-receive-arguments
- `uint8_t *data`
A pointer to the buffer to read into.
@@ -107,10 +107,10 @@ Receive multiple bytes.
---
-### `bool uart_available(void)`
+### `bool uart_available(void)` :id=api-uart-available
Return whether the receive buffer contains data. Call this function to determine if `uart_read()` will return data immediately.
-#### Return Value
+#### Return Value :id=api-uart-available-return
`true` if the receive buffer length is non-zero.