Merge remote-tracking branch 'qmk/master' into merge-2023-03-12

This commit is contained in:
Ilya Zhuravlev 2023-03-18 17:51:58 -06:00
commit 06a2fdcc9c
19466 changed files with 296791 additions and 222541 deletions

View file

@ -7,7 +7,7 @@ This document marks the inaugural Breaking Change merge. A list of changes follo
## Core code formatting with clang-format
* All core files (`drivers/`, `quantum/`, `tests/`, and `tmk_core/`) have been formatted with clang-format
* A travis process to reformat PR's on merge has been instituted
* A travis process to reformat PRs on merge has been instituted
* You can use the new CLI command `qmk cformat` to format before submitting your PR if you wish.
## LUFA USB descriptor cleanup
@ -30,15 +30,15 @@ This document marks the inaugural Breaking Change merge. A list of changes follo
## Backport changes to keymap language files from ZSA fork
* Fixes an issue in the `keymap_br_abnt2.h` file that includes the wrong source (`keymap_common.h` instead of `keymap.h`)
* Updates the `keymap_swedish.h` file to be specific to swedish, and not just "nordic" in general.
* Any keymaps using this will need to remove `NO_*` and replace it with `SE_*`.
* Updates the `keymap_swedish.h` file to be specific to swedish, and not just "nordic" in general.
* Any keymaps using this will need to remove `NO_*` and replace it with `SE_*`.
## Update repo to use LUFA as a git submodule
* `/lib/LUFA` removed from the repo
* LUFA set as a submodule, pointing to qmk/lufa
* This should allow more flexibility with LUFA, and allow us to keep the sub-module up to date, a lot more easily. It was ~2 years out of date with no easy path to fix that. This prevents that from being an issue in the future
## Migrating `ACTION_BACKLIGHT_*()` entries in `fn_actions` to `BL_` keycodes
* `fn_actions` is deprecated, and its functionality has been superseded by direct keycodes and `process_record_user()`

View file

@ -56,19 +56,19 @@ You can now define up to 32 macros in your `keymap.json` file, as used by [QMK C
"keyboard": "handwired/my_macropad",
"keymap": "my_keymap",
"macros": [
[ // first listed is MACRO_0...
[ // first listed is QK_MACRO_0...
{"action":"down", "keycodes": ["LSFT"]},
"hello world1",
{"action": "up","keycodes": ["LSFT"]}
],
[ // ...then MACRO_1...
[ // ...then QK_MACRO_1...
{"action":"tap", "keycodes": ["LCTL", "LALT", "DEL"]}
],
[ // ...then MACRO_2...
[ // ...then QK_MACRO_2...
"ding!",
{"action":"beep"}
],
[ // ...and MACRO_3.
[ // ...and QK_MACRO_3.
{"action":"tap", "keycodes": ["F1"]},
{"action":"delay", "duration": "1000"},
{"action":"tap", "keycodes": ["PGDN"]}
@ -76,7 +76,7 @@ You can now define up to 32 macros in your `keymap.json` file, as used by [QMK C
],
"layout": "LAYOUT_all",
"layers": [
["MACRO_0", "MACRO_1", "MACRO_2", "MACRO_3"]
["QK_MACRO_0", "QK_MACRO_1", "QK_MACRO_2", "QK_MACRO_3"]
]
}
```

510
docs/ChangeLog/20221126.md Normal file
View file

@ -0,0 +1,510 @@
# QMK Breaking Changes - 2022 November 26 Changelog
## Notable Features :id=notable-features
### Autocorrect ([#15699](https://github.com/qmk/qmk_firmware/pull/15699)) :id=autocorrect
_@getreuer_ in their infinite wisdom decided that autocorrect was a feature needed by QMK. As is customary, _@drashna_ adapted it to core and got it into a state that everyone else can use it. See [Feature: Autocorrect](feature_autocorrect.md) for more ifnormation (grin).
## Changes Requiring User Action :id=changes-requiring-user-action
### Updated Keyboard Codebases :id=updated-keyboard-codebases
The following keyboards have had their source moved within QMK:
| Old Keyboard Name | New Keyboard Name |
|--------------------------------------|--------------------------------------|
| converter/numeric_keypad_IIe | converter/numeric_keypad_iie |
| durgod/k3x0/k310 | durgod/k310 |
| durgod/k3x0/k320 | durgod/k320 |
| emptystring/NQG | emptystring/nqg |
| handwired/hillside/46 | hillside/46 |
| handwired/hillside/48 | hillside/48 |
| handwired/hillside/52 | hillside/52 |
| maple_computing/christmas_tree/V2017 | maple_computing/christmas_tree/v2017 |
### Keycodes refactoring :id=keycodes-overhaul-user-action
QMK's keycodes got a very significant overhaul this breaking changes cycle, with the bulk of the work done by _@zvecr_ and _@fauxpark_ -- renaming, reordering, removing has been their focus in this area. In an attempt to standardise interoperation with host applications, keycode values now have strong versioning so that any connected application has confidence that the keys it thinks exist on the board actually match up with what's compiled in. These strongly-versioned keycode definitions are now published online and will not change, so tools that remap keycodes have a reference to work with. In future versions of QMK, any new or changed keycodes will result in a new version specification. See [API docs](api_docs.md#qmk-constants) for more information on the published versions if you're writing a tool to manage keycodes.
In most cases user keymaps in the repository have already been updated to reflect the new naming scheme. In some cases user keymaps outside the repository may strike a missing keycode with the old name -- it's highly likely that the name had already been deprecated for some time, and should have been updated previously.
See below for the full list of changesets.
!> Keycode aliases have been put in place in most cases to cater for "old names" being mapped to "new names" -- the documentation already reflects all the new naming of keys.
### Configuration Item Refactoring :id=config-refactoring
A number of configuration items have been renamed for consistency.
RGB Matrix configuration:
| Old Config | New Config |
|-------------------------|-------------------------|
| DRIVER_LED_COUNT | RGB_MATRIX_LED_COUNT |
| RGB_DISABLE_TIMEOUT | RGB_MATRIX_TIMEOUT |
| RGB_MATRIX_STARTUP_HUE | RGB_MATRIX_DEFAULT_HUE |
| RGB_MATRIX_STARTUP_MODE | RGB_MATRIX_DEFAULT_MODE |
| RGB_MATRIX_STARTUP_SAT | RGB_MATRIX_DEFAULT_SAT |
| RGB_MATRIX_STARTUP_SPD | RGB_MATRIX_DEFAULT_SPD |
| RGB_MATRIX_STARTUP_VAL | RGB_MATRIX_DEFAULT_VAL |
LED Matrix configuration:
| Old Config | New Config |
|-------------------------|-------------------------|
| DRIVER_LED_COUNT | LED_MATRIX_LED_COUNT |
| LED_DISABLE_TIMEOUT | LED_MATRIX_TIMEOUT |
| LED_MATRIX_STARTUP_MODE | LED_MATRIX_DEFAULT_MODE |
| LED_MATRIX_STARTUP_SPD | LED_MATRIX_DEFAULT_SPD |
| LED_MATRIX_STARTUP_VAL | LED_MATRIX_DEFAULT_VAL |
Joystick configuration:
| Old Config | New Config |
|--------------------------|--------------------------|
| JOYSTICK_AXES_COUNT | JOYSTICK_AXIS_COUNT |
| JOYSTICK_AXES_RESOLUTION | JOYSTICK_AXIS_RESOLUTION |
### Data-driven USB IDs Refactoring ([#18152](https://github.com/qmk/qmk_firmware/pull/18152)) :id=usb-ids-Refactoring
QMK has decided to deprecate the specification of USB IDs inside `config.h` in favour of `info.json`, leaving data-driven as the only method to specify USB information. As per the deprecation schedule put forward last breaking changes cycle, USB information must be specified in `info.json` instead.
Previously in `config.h`:
```c
#define VENDOR_ID 0x1234
#define PRODUCT_ID 0x5678
#define DEVICE_VER 0x0001
#define MANUFACTURER Me
#define PRODUCT MyKeyboard
```
Replaced by `info.json`:
```json
{
"keyboard_name": "MyKeyboard",
"manufacturer": "Me",
"usb": {
"vid": "0x1234",
"pid": "0x5678",
"device_version": "0.0.1"
}
}
```
### LED Indicator callback refactoring ([#14864](https://github.com/qmk/qmk_firmware/pull/18450)) :id=led-callback-refactor
_RGB Matrix_ and _LED Matrix_ Indicator display code was traditionally difficult to override in keymaps as they did not follow the standard pattern of `bool *_kb()` deferring to `bool *_user()` functions, allowing signalling to the higher level that processing had already been done.
This changes the standard callback model to allow for a base implementation to be provided by a keyboard, but also still allow for keymap-level overrides without needing to modify the keyboard's code.
The old RGB Matrix keymap code went something like this:
```c
void rgb_matrix_indicators_user(void) {
// keymap LED code
}
```
...but the new RGB Matrix keymap code looks like this:
```c
bool rgb_matrix_indicators_user(void) {
// keymap LED code
return false;
}
```
Keyboard designers should now structure their keyboard-level routines like the following, in order to allow for keymap overrides:
```c
bool rgb_matrix_indicators_kb(void) {
// Defer to the keymap if they want to override
if (!rgb_matrix_indicators_user()) { return false; }
// keyboard LED code
return true;
}
```
The equivalent transformations should be done for LED Matrix boards.
### Unicode mode refactoring :id=unicode-mode-renaming
Unicode modes were renamed in order to prevent collision with equivalent keycodes. The available values for `UNICODE_SELECTED_MODES` changed -- see [Feature: Unicode](feature_unicode.md#setting-the-input-mode) for the new list of values and how to configure them.
## Notable core changes :id=notable-core
This breaking changes cycle, a lot of the core changes are related to cleanup and refactoring -- commonly called "tech debt".
### Keycodes refactoring :id=keycodes-overhaul-core-changes
We aren't going to list each and every change -- they're far too numerous -- instead, we'll just list the related PRs in order to convey just how wide-reaching these changes were:
* Align audio keycode names ([#18962](https://github.com/qmk/qmk_firmware/pull/18962))
* Align dynamic tapping term keycode names ([#18963](https://github.com/qmk/qmk_firmware/pull/18963))
* Align haptic feedback keycode names ([#18964](https://github.com/qmk/qmk_firmware/pull/18964))
* Deprecate `CAPS_WORD`/`CAPSWRD` for `CW_TOGG` ([#18834](https://github.com/qmk/qmk_firmware/pull/18834))
* Deprecate `KC_LEAD` for `QK_LEAD` ([#18792](https://github.com/qmk/qmk_firmware/pull/18792))
* Deprecate `KC_LOCK` for `QK_LOCK` ([#18796](https://github.com/qmk/qmk_firmware/pull/18796))
* Deprecate `KEY_OVERRIDE_*` keycodes for `KO_*` ([#18843](https://github.com/qmk/qmk_firmware/pull/18843))
* Deprecate `ONESHOT_*` keycodes for `QK_ONE_SHOT_*` ([#18844](https://github.com/qmk/qmk_firmware/pull/18844))
* Deprecate `SECURE_*` keycodes for `QK_SECURE_*` ([#18847](https://github.com/qmk/qmk_firmware/pull/18847))
* Deprecate `VLK_TOG` for `VK_TOGG` ([#18807](https://github.com/qmk/qmk_firmware/pull/18807))
* Initial DD keycode migration ([#18643](https://github.com/qmk/qmk_firmware/pull/18643))
* Macro keycode name refactoring ([#18958](https://github.com/qmk/qmk_firmware/pull/18958))
* Move mousekey keycodes into newly freed up keycode block ([#16076](https://github.com/qmk/qmk_firmware/pull/16076))
* Normalise Auto Shift keycodes ([#18892](https://github.com/qmk/qmk_firmware/pull/18892))
* Normalise Autocorrect keycodes ([#18893](https://github.com/qmk/qmk_firmware/pull/18893))
* Normalise Combo keycodes ([#18877](https://github.com/qmk/qmk_firmware/pull/18877))
* Normalise Dynamic Macro keycodes ([#18939](https://github.com/qmk/qmk_firmware/pull/18939))
* Normalise Joystick and Programmable Button keycodes ([#18832](https://github.com/qmk/qmk_firmware/pull/18832))
* Normalise MIDI keycodes ([#18972](https://github.com/qmk/qmk_firmware/pull/18972))
* Normalise output selection (Bluetooth) keycodes ([#19004](https://github.com/qmk/qmk_firmware/pull/19004))
* Normalise Space Cadet keycodes ([#18864](https://github.com/qmk/qmk_firmware/pull/18864))
* Normalise Unicode keycodes ([#18898](https://github.com/qmk/qmk_firmware/pull/18898))
* Publish constants metadata to API ([#19143](https://github.com/qmk/qmk_firmware/pull/19143))
* Relocate US ANSI shifted keycode aliases ([#18634](https://github.com/qmk/qmk_firmware/pull/18634))
* Remove `KC_DELT` ([#18882](https://github.com/qmk/qmk_firmware/pull/18882))
* Remove `UNICODE_KEY_OSX` and `UC_OSX` ([#18290](https://github.com/qmk/qmk_firmware/pull/18290))
* Remove deprecated RESET keycode alias ([#18271](https://github.com/qmk/qmk_firmware/pull/18271))
* Remove legacy Debug keycode ([#18769](https://github.com/qmk/qmk_firmware/pull/18769))
* Remove legacy EEPROM clear keycodes ([#18782](https://github.com/qmk/qmk_firmware/pull/18782))
* Remove legacy fauxclicky and unicode keycodes ([#18800](https://github.com/qmk/qmk_firmware/pull/18800))
* Remove legacy Grave Escape keycodes ([#18787](https://github.com/qmk/qmk_firmware/pull/18787))
* Remove legacy international keycodes ([#18588](https://github.com/qmk/qmk_firmware/pull/18588))
* Remove legacy keycodes, part 2 ([#18660](https://github.com/qmk/qmk_firmware/pull/18660))
* Remove legacy keycodes, part 3 ([#18669](https://github.com/qmk/qmk_firmware/pull/18669))
* Remove legacy keycodes, part 4 ([#18683](https://github.com/qmk/qmk_firmware/pull/18683))
* Remove legacy keycodes, part 5 ([#18710](https://github.com/qmk/qmk_firmware/pull/18710))
* Remove legacy keycodes, part 6 ([#18740](https://github.com/qmk/qmk_firmware/pull/18740))
* Remove legacy locking caps/num/scroll keycodes ([#18601](https://github.com/qmk/qmk_firmware/pull/18601))
* Remove legacy sendstring keycodes ([#18749](https://github.com/qmk/qmk_firmware/pull/18749))
* Reworked backlight keycodes. ([#18961](https://github.com/qmk/qmk_firmware/pull/18961))
### Board Converters :id=board-converters
There was additional work in the space of board converters -- historically QMK allowed for "converting" a Pro Micro build to a QMK Proton-C build. The last few versions of QMK have added support for replacement boards much like the Proton-C, and this quarter was no exception:
* Add Bonsai C4 as a platform board file ([#18901](https://github.com/qmk/qmk_firmware/pull/18901))
* Add converter support to keymap.json ([#18776](https://github.com/qmk/qmk_firmware/pull/18776))
* Add Elite-C to converters ([#18309](https://github.com/qmk/qmk_firmware/pull/18309))
* Add Elite-Pi converter ([#18236](https://github.com/qmk/qmk_firmware/pull/18236))
* Allow QK_MAKE to work with converters ([#18637](https://github.com/qmk/qmk_firmware/pull/18637))
See [Feature: Converters](feature_converters.md) for the full list of board conversions available.
### Pointing and Digitizer device updates :id=pointing-and-digitizer
Both pointing devices and digitizer got a host of updates this cycle. Inertia, automatic mouse layers, fixes for preventing sleep... you even get more buttons with digitizers!
* add "inertia" mode for mouse keys ([#18774](https://github.com/qmk/qmk_firmware/pull/18774))
* Digitizer feature improvements ([#19034](https://github.com/qmk/qmk_firmware/pull/19034))
* Enabling Pointing Device support in register code functions ([#18363](https://github.com/qmk/qmk_firmware/pull/18363))
* Feature: pointing device automatic mouse layer ([#17962](https://github.com/qmk/qmk_firmware/pull/17962))
* Fix mouse report comparison failing on shared EP (fixes KB preventing sleep) ([#18060](https://github.com/qmk/qmk_firmware/pull/18060))
* Fix mouse use within send_string ([#18659](https://github.com/qmk/qmk_firmware/pull/18659))
* Handle mouse keys more consistently ([#18513](https://github.com/qmk/qmk_firmware/pull/18513))
* Invert pointing device motion pin for cirque touchpads ([#18404](https://github.com/qmk/qmk_firmware/pull/18404))
* Refactor more host code (programmable button & digitizer) ([#18565](https://github.com/qmk/qmk_firmware/pull/18565))
## Full changelist :id=full-changelist
Core:
* quantum: led: split out led_update_ports() for customization of led behaviour ([#14452](https://github.com/qmk/qmk_firmware/pull/14452))
* Add getreuer's Autocorrect feature to core ([#15699](https://github.com/qmk/qmk_firmware/pull/15699))
* Move mousekey keycodes into newly freed up keycode block ([#16076](https://github.com/qmk/qmk_firmware/pull/16076))
* Introduce pointing device specific debug messages ([#17663](https://github.com/qmk/qmk_firmware/pull/17663))
* PWM Backlight for RP2040 ([#17706](https://github.com/qmk/qmk_firmware/pull/17706))
* Adjust PWM hardware audio driver for RP2040 ([#17723](https://github.com/qmk/qmk_firmware/pull/17723))
* Prevent tap dance from wiping dynamic macros ([#17880](https://github.com/qmk/qmk_firmware/pull/17880))
* Feature: pointing device automatic mouse layer ([#17962](https://github.com/qmk/qmk_firmware/pull/17962))
* Allow custom timings for WS2812 PIO driver ([#18006](https://github.com/qmk/qmk_firmware/pull/18006))
* Use `TAP_CODE_DELAY` for encoder mapping by default. Add docs. ([#18098](https://github.com/qmk/qmk_firmware/pull/18098))
* Move Oneshot mod callbacks to after mods are set ([#18101](https://github.com/qmk/qmk_firmware/pull/18101))
* mcp23018: add return status to init ([#18178](https://github.com/qmk/qmk_firmware/pull/18178))
* Switch over MANUFACTURER and PRODUCT to string literals ([#18183](https://github.com/qmk/qmk_firmware/pull/18183))
* Remove deprecated USBasp and bootloadHID bootloader types ([#18195](https://github.com/qmk/qmk_firmware/pull/18195))
* Chromeos keycodes ([#18212](https://github.com/qmk/qmk_firmware/pull/18212))
* VIA V3 - The Custom UI Update ([#18222](https://github.com/qmk/qmk_firmware/pull/18222))
* Move bootloader.mk to platforms ([#18228](https://github.com/qmk/qmk_firmware/pull/18228))
* Simplify extrakeys sending at the host driver level ([#18230](https://github.com/qmk/qmk_firmware/pull/18230))
* Add unicode mode change callbacks ([#18235](https://github.com/qmk/qmk_firmware/pull/18235))
* Add Elite-Pi converter ([#18236](https://github.com/qmk/qmk_firmware/pull/18236))
* Better handle EEPROM reset keycode ([#18244](https://github.com/qmk/qmk_firmware/pull/18244))
* Work around WinCompose issue for U+Axxx or U+Exxx ([#18260](https://github.com/qmk/qmk_firmware/pull/18260))
* Remove deprecated RESET keycode alias ([#18271](https://github.com/qmk/qmk_firmware/pull/18271))
* Move Bluetooth-related function calls up to host/keyboard level ([#18274](https://github.com/qmk/qmk_firmware/pull/18274))
* Added analog support for WB32 MCU. ([#18289](https://github.com/qmk/qmk_firmware/pull/18289))
* Remove `UNICODE_KEY_OSX` and `UC_OSX` ([#18290](https://github.com/qmk/qmk_firmware/pull/18290))
* Add Elite-C to converters ([#18309](https://github.com/qmk/qmk_firmware/pull/18309))
* RN42 driver: small cleanups ([#18310](https://github.com/qmk/qmk_firmware/pull/18310))
* Reboot wb32 devices after flashing ([#18323](https://github.com/qmk/qmk_firmware/pull/18323))
* Refactor Unicode feature ([#18333](https://github.com/qmk/qmk_firmware/pull/18333))
* Move fake EE_HANDS from EEPROM init. ([#18352](https://github.com/qmk/qmk_firmware/pull/18352))
* Enabling Pointing Device support in register code functions ([#18363](https://github.com/qmk/qmk_firmware/pull/18363))
* Start Bluetooth API ([#18366](https://github.com/qmk/qmk_firmware/pull/18366))
* Add UART support for Kinetis boards ([#18370](https://github.com/qmk/qmk_firmware/pull/18370))
* [QP] Add RGB565 surface. Docs clarification, cleanup, tabsification, and reordering. ([#18396](https://github.com/qmk/qmk_firmware/pull/18396))
* Change `DRIVER_LED_COUNT` to `{LED,RGB}_MATRIX_LED_COUNT` ([#18399](https://github.com/qmk/qmk_firmware/pull/18399))
* Invert pointing device motion pin for cirque touchpads ([#18404](https://github.com/qmk/qmk_firmware/pull/18404))
* Change `{LED,RGB}_DISABLE_TIMEOUT` to `{LED,RGB}_MATRIX_TIMEOUT` ([#18415](https://github.com/qmk/qmk_firmware/pull/18415))
* rewrite locking in split transaction handlers ([#18417](https://github.com/qmk/qmk_firmware/pull/18417))
* remove busy waiting from rgblight functions ([#18418](https://github.com/qmk/qmk_firmware/pull/18418))
* Serial-protocol: always clear receive queue on main half of split keyboard ([#18419](https://github.com/qmk/qmk_firmware/pull/18419))
* Stabilize RP2040 Half-duplex PIO split comms take 2 ([#18421](https://github.com/qmk/qmk_firmware/pull/18421))
* Copy RP2040 vector table to RAM on startup ([#18424](https://github.com/qmk/qmk_firmware/pull/18424))
* Further refactoring of joystick feature ([#18437](https://github.com/qmk/qmk_firmware/pull/18437))
* Start moving towards introspection-based data retrieval ([#18441](https://github.com/qmk/qmk_firmware/pull/18441))
* RP2040: use built-in integer hardware divider and optimized i64 multiplication ([#18464](https://github.com/qmk/qmk_firmware/pull/18464))
* Only trigger encoder callbacks on primary side ([#18467](https://github.com/qmk/qmk_firmware/pull/18467))
* Handle mouse keys more consistently ([#18513](https://github.com/qmk/qmk_firmware/pull/18513))
* Gentoo install script — build newlib with `nano` USE flag ([#18527](https://github.com/qmk/qmk_firmware/pull/18527))
* Small un/register_code() cleanups ([#18544](https://github.com/qmk/qmk_firmware/pull/18544))
* Refactor more host code (programmable button & digitizer) ([#18565](https://github.com/qmk/qmk_firmware/pull/18565))
* Don't clear keys on layer change unless STRICT_LAYER_RELEASE is enabled ([#18577](https://github.com/qmk/qmk_firmware/pull/18577))
* Remove legacy international keycodes ([#18588](https://github.com/qmk/qmk_firmware/pull/18588))
* onekey: Enable ADC for STM32F072 Discovery ([#18592](https://github.com/qmk/qmk_firmware/pull/18592))
* Implement split comms watchdog ([#18599](https://github.com/qmk/qmk_firmware/pull/18599))
* Remove legacy locking caps/num/scroll keycodes ([#18601](https://github.com/qmk/qmk_firmware/pull/18601))
* Use `get_u16_str` instead of `snprintf` in `autoshift_timer_report` ([#18606](https://github.com/qmk/qmk_firmware/pull/18606))
* Refactor `send_extra` ([#18615](https://github.com/qmk/qmk_firmware/pull/18615))
* LUFA: Consolidate report sending code ([#18629](https://github.com/qmk/qmk_firmware/pull/18629))
* Relocate US ANSI shifted keycode aliases ([#18634](https://github.com/qmk/qmk_firmware/pull/18634))
* Allow QK_MAKE to work with converters ([#18637](https://github.com/qmk/qmk_firmware/pull/18637))
* Programmable Button API refactor and improve docs ([#18641](https://github.com/qmk/qmk_firmware/pull/18641))
* Initial DD keycode migration ([#18643](https://github.com/qmk/qmk_firmware/pull/18643))
* Remove legacy keycodes, part 2 ([#18660](https://github.com/qmk/qmk_firmware/pull/18660))
* Remove legacy keycodes, part 3 ([#18669](https://github.com/qmk/qmk_firmware/pull/18669))
* Remove legacy keycodes, part 4 ([#18683](https://github.com/qmk/qmk_firmware/pull/18683))
* Revert "mcp23018: add return status to init" ([#18709](https://github.com/qmk/qmk_firmware/pull/18709))
* Remove legacy keycodes, part 5 ([#18710](https://github.com/qmk/qmk_firmware/pull/18710))
* Make QP driver init functions weak. ([#18717](https://github.com/qmk/qmk_firmware/pull/18717))
* Add unit tests for HOLD_ON_OTHER_KEY_PRESS ([#18721](https://github.com/qmk/qmk_firmware/pull/18721))
* Remove legacy keycodes, part 6 ([#18740](https://github.com/qmk/qmk_firmware/pull/18740))
* Remove legacy sendstring keycodes ([#18749](https://github.com/qmk/qmk_firmware/pull/18749))
* 4 Driver support for IS31FL3737 ([#18750](https://github.com/qmk/qmk_firmware/pull/18750))
* Remove quantum/audio from global VPATH ([#18753](https://github.com/qmk/qmk_firmware/pull/18753))
* Widen the ARM Cortex-M family support. Allow USB peripheral change. ([#18767](https://github.com/qmk/qmk_firmware/pull/18767))
* Remove legacy Debug keycode ([#18769](https://github.com/qmk/qmk_firmware/pull/18769))
* add "inertia" mode for mouse keys ([#18774](https://github.com/qmk/qmk_firmware/pull/18774))
* Remove legacy EEPROM clear keycodes ([#18782](https://github.com/qmk/qmk_firmware/pull/18782))
* Remove legacy Grave Escape keycodes ([#18787](https://github.com/qmk/qmk_firmware/pull/18787))
* Deprecate `KC_LEAD` for `QK_LEAD` ([#18792](https://github.com/qmk/qmk_firmware/pull/18792))
* Deprecate `KC_LOCK` for `QK_LOCK` ([#18796](https://github.com/qmk/qmk_firmware/pull/18796))
* Remove legacy fauxclicky and unicode keycodes ([#18800](https://github.com/qmk/qmk_firmware/pull/18800))
* Generalise CTPC logic from common_features ([#18803](https://github.com/qmk/qmk_firmware/pull/18803))
* Deprecate `VLK_TOG` for `VK_TOGG` ([#18807](https://github.com/qmk/qmk_firmware/pull/18807))
* ChibiOS USB: Add a dummy IN callback to work around LLD bugs ([#18811](https://github.com/qmk/qmk_firmware/pull/18811))
* Normalise Joystick and Programmable Button keycodes ([#18832](https://github.com/qmk/qmk_firmware/pull/18832))
* Deprecate `CAPS_WORD`/`CAPSWRD` for `CW_TOGG` ([#18834](https://github.com/qmk/qmk_firmware/pull/18834))
* added BS_TOGG so BS_SWAP and BS_NORM can be on a single key ([#18837](https://github.com/qmk/qmk_firmware/pull/18837))
* Remove some assumptions on sequential keycode ranges ([#18838](https://github.com/qmk/qmk_firmware/pull/18838))
* Deprecate `KEY_OVERRIDE_*` keycodes for `KO_*` ([#18843](https://github.com/qmk/qmk_firmware/pull/18843))
* Deprecate `ONESHOT_*` keycodes for `QK_ONE_SHOT_*` ([#18844](https://github.com/qmk/qmk_firmware/pull/18844))
* Deprecate `SECURE_*` keycodes for `QK_SECURE_*` ([#18847](https://github.com/qmk/qmk_firmware/pull/18847))
* Normalise Space Cadet keycodes ([#18864](https://github.com/qmk/qmk_firmware/pull/18864))
* Allow overriding of dynamic keymap start address. ([#18867](https://github.com/qmk/qmk_firmware/pull/18867))
* Formalise keyboard- and user-specific EEPROM blocks ([#18874](https://github.com/qmk/qmk_firmware/pull/18874))
* Normalise Combo keycodes ([#18877](https://github.com/qmk/qmk_firmware/pull/18877))
* Remove rgblight_list.h ([#18878](https://github.com/qmk/qmk_firmware/pull/18878))
* Remove `KC_DELT` ([#18882](https://github.com/qmk/qmk_firmware/pull/18882))
* Simplify Keymap Config EEPROM ([#18886](https://github.com/qmk/qmk_firmware/pull/18886))
* Normalise Auto Shift keycodes ([#18892](https://github.com/qmk/qmk_firmware/pull/18892))
* Normalise Autocorrect keycodes ([#18893](https://github.com/qmk/qmk_firmware/pull/18893))
* Normalise Unicode keycodes ([#18898](https://github.com/qmk/qmk_firmware/pull/18898))
* Add Bonsai C4 as a platform board file ([#18901](https://github.com/qmk/qmk_firmware/pull/18901))
* Normalise Dynamic Macro keycodes ([#18939](https://github.com/qmk/qmk_firmware/pull/18939))
* Reduce includes for sequencer header ([#18946](https://github.com/qmk/qmk_firmware/pull/18946))
* Reduce includes for crc header ([#18947](https://github.com/qmk/qmk_firmware/pull/18947))
* Reduce includes for caps_word header ([#18948](https://github.com/qmk/qmk_firmware/pull/18948))
* Reduce includes for wpm header ([#18949](https://github.com/qmk/qmk_firmware/pull/18949))
* Reduce includes for dip_switch header ([#18951](https://github.com/qmk/qmk_firmware/pull/18951))
* Reduce includes for send_string header ([#18952](https://github.com/qmk/qmk_firmware/pull/18952))
* Macro keycode name refactoring ([#18958](https://github.com/qmk/qmk_firmware/pull/18958))
* Remove thermal printer. ([#18959](https://github.com/qmk/qmk_firmware/pull/18959))
* Reworked backlight keycodes. ([#18961](https://github.com/qmk/qmk_firmware/pull/18961))
* Align audio keycode names ([#18962](https://github.com/qmk/qmk_firmware/pull/18962))
* Align dynamic tapping term keycode names ([#18963](https://github.com/qmk/qmk_firmware/pull/18963))
* Align haptic feedback keycode names ([#18964](https://github.com/qmk/qmk_firmware/pull/18964))
* NVRAM refactor, phase 1. ([#18969](https://github.com/qmk/qmk_firmware/pull/18969))
* Normalise MIDI keycodes ([#18972](https://github.com/qmk/qmk_firmware/pull/18972))
* Normalise output selection (Bluetooth) keycodes ([#19004](https://github.com/qmk/qmk_firmware/pull/19004))
* Move EFL wear-leveling driver to be default for F1, F3, F4, L4, G4, WB32, GD32V. ([#19020](https://github.com/qmk/qmk_firmware/pull/19020))
* Digitizer feature improvements ([#19034](https://github.com/qmk/qmk_firmware/pull/19034))
* Joystick feature improvements ([#19052](https://github.com/qmk/qmk_firmware/pull/19052))
* Add default limit to OLED dirty processing ([#19068](https://github.com/qmk/qmk_firmware/pull/19068))
* Change `RGB_MATRIX_STARTUP_*` defines to `RGB_MATRIX_DEFAULT_*` ([#19079](https://github.com/qmk/qmk_firmware/pull/19079))
* Change `LED_MATRIX_STARTUP_*` defines to `LED_MATRIX_DEFAULT_*` ([#19080](https://github.com/qmk/qmk_firmware/pull/19080))
* Extend eeconfig kb/user datablock API ([#19094](https://github.com/qmk/qmk_firmware/pull/19094))
* Remove .noci functionality ([#19122](https://github.com/qmk/qmk_firmware/pull/19122))
CLI:
* Reject json with duplicate keys ([#18108](https://github.com/qmk/qmk_firmware/pull/18108))
* Add pointing device support to data driven config ([#18215](https://github.com/qmk/qmk_firmware/pull/18215))
* Disconnect `usb.device_ver` ([#18259](https://github.com/qmk/qmk_firmware/pull/18259))
* Normalise info_config.h define generation ([#18439](https://github.com/qmk/qmk_firmware/pull/18439))
* Generate DD RGBLight/LED/RGB Matrix animation defines ([#18459](https://github.com/qmk/qmk_firmware/pull/18459))
* Add converter support to keymap.json ([#18776](https://github.com/qmk/qmk_firmware/pull/18776))
* Ensure consistent clean behaviour ([#18781](https://github.com/qmk/qmk_firmware/pull/18781))
* Format DD mappings and schemas ([#18924](https://github.com/qmk/qmk_firmware/pull/18924))
* Publish hjson files as json ([#18996](https://github.com/qmk/qmk_firmware/pull/18996))
* Add raw output option for QGF/QFF files. ([#18998](https://github.com/qmk/qmk_firmware/pull/18998))
* Improve LED config parsing error messages ([#19007](https://github.com/qmk/qmk_firmware/pull/19007))
* Revert "Add pointing device support to data driven config (#18215)" ([#19063](https://github.com/qmk/qmk_firmware/pull/19063))
* Additional DD backlight config ([#19124](https://github.com/qmk/qmk_firmware/pull/19124))
* Publish constants metadata to API ([#19143](https://github.com/qmk/qmk_firmware/pull/19143))
Submodule updates:
* Use a macro to compute the size of arrays at compile time ([#18044](https://github.com/qmk/qmk_firmware/pull/18044))
* Update pico-sdk to version 1.4.0 ([#18423](https://github.com/qmk/qmk_firmware/pull/18423))
Keyboards:
* Rework PS/2 driver selection ([#17892](https://github.com/qmk/qmk_firmware/pull/17892))
* Durgod K310/K320 Refactor ([#18224](https://github.com/qmk/qmk_firmware/pull/18224))
* Optimise LAYOUT macro generation ([#18262](https://github.com/qmk/qmk_firmware/pull/18262))
* Rename keyboards with uppercase letters ([#18268](https://github.com/qmk/qmk_firmware/pull/18268))
* Remove legacy USE_SERIAL define ([#18292](https://github.com/qmk/qmk_firmware/pull/18292))
* Resolve conflict merging master to develop ([#18297](https://github.com/qmk/qmk_firmware/pull/18297))
* Remove legacy define USE_SERIAL_PD2 ([#18298](https://github.com/qmk/qmk_firmware/pull/18298))
* Remove legacy define SERIAL_USE_MULTI_TRANSACTION ([#18299](https://github.com/qmk/qmk_firmware/pull/18299))
* Adapt spidey3 userspace to recent unicode refactoring ([#18345](https://github.com/qmk/qmk_firmware/pull/18345))
* Remove remaining use of terminal keys and related comment labels ([#18402](https://github.com/qmk/qmk_firmware/pull/18402))
* Add DD mapping for LED/RGB Matrix center ([#18432](https://github.com/qmk/qmk_firmware/pull/18432))
* develop updates for Drashna Keymaps ([#18472](https://github.com/qmk/qmk_firmware/pull/18472))
* Remove lingering `DRIVER_LED_TOTAL` references ([#18475](https://github.com/qmk/qmk_firmware/pull/18475))
* Remove lingering `DRIVER_LED_TOTAL` references ([#18594](https://github.com/qmk/qmk_firmware/pull/18594))
* update andrebrait GMMK Pro keymap ([#18608](https://github.com/qmk/qmk_firmware/pull/18608))
* AnnePro2: Adjust RGB flushing ([#18640](https://github.com/qmk/qmk_firmware/pull/18640))
* Remove lingering `DRIVER_LED_TOTAL` references ([#18662](https://github.com/qmk/qmk_firmware/pull/18662))
* Update snowe's KC_RESET to use QK_BOOT ([#18667](https://github.com/qmk/qmk_firmware/pull/18667))
* Remove some .gitignore files ([#18689](https://github.com/qmk/qmk_firmware/pull/18689))
* Remove keymaps that still reference legacy macros ([#18690](https://github.com/qmk/qmk_firmware/pull/18690))
* Remove keymaps that still reference legacy macros ([#18693](https://github.com/qmk/qmk_firmware/pull/18693))
* Remove stale userspace/keymaps ([#18700](https://github.com/qmk/qmk_firmware/pull/18700))
* Update keyboards readme ([#18714](https://github.com/qmk/qmk_firmware/pull/18714))
* Allow changes to the moonlander default music map ([#18715](https://github.com/qmk/qmk_firmware/pull/18715))
* led_update_kb -> led_update_ports where appropriate ([#18716](https://github.com/qmk/qmk_firmware/pull/18716))
* Update converter/usb_usb user keymaps to use LAYOUT_fullsize ([#18720](https://github.com/qmk/qmk_firmware/pull/18720))
* Remove RGBLIGHT_ANIMATION and clean up effect defines for G-K ([#18726](https://github.com/qmk/qmk_firmware/pull/18726))
* Remove RGBLIGHT_ANIMATION and clean up effect defines for L-Q ([#18727](https://github.com/qmk/qmk_firmware/pull/18727))
* Remove RGBLIGHT_ANIMATION and clean up effect defines for R-Z ([#18728](https://github.com/qmk/qmk_firmware/pull/18728))
* Remove RGBLIGHT_ANIMATION and clean up effect defines for layouts+users ([#18729](https://github.com/qmk/qmk_firmware/pull/18729))
* Update info.json configs to explicitly list RGBLIGHT animations ([#18730](https://github.com/qmk/qmk_firmware/pull/18730))
* A little personal cleanup after #18726 and #18729 ([#18734](https://github.com/qmk/qmk_firmware/pull/18734))
* Move Hillside out of handwired ([#18751](https://github.com/qmk/qmk_firmware/pull/18751))
* wilba_tech: allow keymaps to override backlight_effect_indicators() ([#18791](https://github.com/qmk/qmk_firmware/pull/18791))
* Remove broken userspace and keymaps ([#18806](https://github.com/qmk/qmk_firmware/pull/18806))
* Add support for KBDfans Odin V2 ([#18910](https://github.com/qmk/qmk_firmware/pull/18910))
* Remove more `UNUSED_PINS` defines ([#18940](https://github.com/qmk/qmk_firmware/pull/18940))
* Remove hardcoded VIA keycode range ([#18956](https://github.com/qmk/qmk_firmware/pull/18956))
* KC_GESC -> QK_GESC, better alignment for OCD ([#19018](https://github.com/qmk/qmk_firmware/pull/19018))
* Add missing `manufacturer` fields ([#19065](https://github.com/qmk/qmk_firmware/pull/19065))
* Update use of legacy keycodes ([#19120](https://github.com/qmk/qmk_firmware/pull/19120))
Keyboard fixes:
* [GMMK Pro] Fix unintentional taps to the volume keys when using the encoder ([#17129](https://github.com/qmk/qmk_firmware/pull/17129))
* Luna keyboard pet OLED timeout fix ([#17189](https://github.com/qmk/qmk_firmware/pull/17189))
* Handle escaping of manufacturer/product strings ([#18194](https://github.com/qmk/qmk_firmware/pull/18194))
* kegen/gboy: add manufacturer string ([#18196](https://github.com/qmk/qmk_firmware/pull/18196))
* Ensure all keyboards have a bootloader set ([#18234](https://github.com/qmk/qmk_firmware/pull/18234))
* Reverse keymap search order ([#18449](https://github.com/qmk/qmk_firmware/pull/18449))
* Fixup cradio bootloader/processor ([#18477](https://github.com/qmk/qmk_firmware/pull/18477))
* onekey: enable ADC for Bluepill and Blackpill ([#18545](https://github.com/qmk/qmk_firmware/pull/18545))
* Fixup controllerworks/mini42 ([#18553](https://github.com/qmk/qmk_firmware/pull/18553))
* RESET -> QK_BOOT user keymaps ([#18560](https://github.com/qmk/qmk_firmware/pull/18560))
* Fixup linworks/fave84h ([#18593](https://github.com/qmk/qmk_firmware/pull/18593))
* Fix compilation of 1upkeyboards on develop ([#18618](https://github.com/qmk/qmk_firmware/pull/18618))
* Various keyboard fixes ([#18649](https://github.com/qmk/qmk_firmware/pull/18649))
* Fixup twig50 ([#18651](https://github.com/qmk/qmk_firmware/pull/18651))
* Fixup handwired/jopr — remove deprecated keycode ([#18668](https://github.com/qmk/qmk_firmware/pull/18668))
* Fixup keychron/q3 ([#18687](https://github.com/qmk/qmk_firmware/pull/18687))
* Fixup dumbpad/v3x ([#18692](https://github.com/qmk/qmk_firmware/pull/18692))
* Fix aurora/sweep ([#18701](https://github.com/qmk/qmk_firmware/pull/18701))
* Fix build failures uncovered by #18753 ([#18789](https://github.com/qmk/qmk_firmware/pull/18789))
* Fixup emptystring/nqg ([#18804](https://github.com/qmk/qmk_firmware/pull/18804))
* Fixup controllerwords/mini36 ([#18840](https://github.com/qmk/qmk_firmware/pull/18840))
* Fixup 1upkeyboards/pi60_rgb ([#18858](https://github.com/qmk/qmk_firmware/pull/18858))
* Fixup doio/kb16 ([#18859](https://github.com/qmk/qmk_firmware/pull/18859))
* Fixup keebio/sinc/rev3 ([#18866](https://github.com/qmk/qmk_firmware/pull/18866))
* elephant42: fix default keymap ([#18884](https://github.com/qmk/qmk_firmware/pull/18884))
* Properly fix elephant42 ([#18908](https://github.com/qmk/qmk_firmware/pull/18908))
* Fix syntax error introduced in #18800 ([#18933](https://github.com/qmk/qmk_firmware/pull/18933))
* Resolve info.json/rules.mk feature conflicts in three boards ([#18942](https://github.com/qmk/qmk_firmware/pull/18942))
* Fix DD warnings for RGBKB boards ([#18944](https://github.com/qmk/qmk_firmware/pull/18944))
* Fix "no matrix definition" errors for some boards ([#18954](https://github.com/qmk/qmk_firmware/pull/18954))
* LED config fixes ([#18973](https://github.com/qmk/qmk_firmware/pull/18973))
* `handwired/swiftrax/walter`: fix layout mismatch ([#18974](https://github.com/qmk/qmk_firmware/pull/18974))
* Fix use of shifted custom keycode ([#18978](https://github.com/qmk/qmk_firmware/pull/18978))
* `pizzakeyboards/pizza65`: fix layouts ([#18979](https://github.com/qmk/qmk_firmware/pull/18979))
* `cannonkeys/db60/hotswap`: fix layouts ([#18982](https://github.com/qmk/qmk_firmware/pull/18982))
* `handwired/swiftrax/cowfish`: fix layouts ([#18984](https://github.com/qmk/qmk_firmware/pull/18984))
* Fixup hotdox76v2 on develop ([#18991](https://github.com/qmk/qmk_firmware/pull/18991))
* `mechlovin/adelais/standard_led/avr/rev1`: fix layout ([#18997](https://github.com/qmk/qmk_firmware/pull/18997))
* `gboards/gergoplex`: fix matrix pins ([#18999](https://github.com/qmk/qmk_firmware/pull/18999))
* Fixup keychron/q1/iso_encoder ([#19006](https://github.com/qmk/qmk_firmware/pull/19006))
* Rollback unrelated changes from previous PR. ([#19015](https://github.com/qmk/qmk_firmware/pull/19015))
* Fixup bn006 on develop ([#19029](https://github.com/qmk/qmk_firmware/pull/19029))
* onekey: disable NKRO and mousekeys by default ([#19038](https://github.com/qmk/qmk_firmware/pull/19038))
* Fix up laser_ninja/pumpkin_pad ([#19060](https://github.com/qmk/qmk_firmware/pull/19060))
* Fixup keychron/q6 ([#19066](https://github.com/qmk/qmk_firmware/pull/19066))
* Fixup handwired/alcor_dactyl ([#19072](https://github.com/qmk/qmk_firmware/pull/19072))
* Fix some old keycodes ([#19086](https://github.com/qmk/qmk_firmware/pull/19086))
* Update more `DRIVER_LED_TOTAL` defines to `RGB_MATRIX_LED_COUNT` ([#19089](https://github.com/qmk/qmk_firmware/pull/19089))
* Fix references to `mouse_report_t` (which doesnt exist) ([#19107](https://github.com/qmk/qmk_firmware/pull/19107))
* Fixup keychron/q5 ([#19119](https://github.com/qmk/qmk_firmware/pull/19119))
* Fixup aeboards/satellite ([#19137](https://github.com/qmk/qmk_firmware/pull/19137))
* Fixup aurora/corne on develop ([#19144](https://github.com/qmk/qmk_firmware/pull/19144))
* Minor lint fixes for various info.json ([#19146](https://github.com/qmk/qmk_firmware/pull/19146))
Others:
* Add DD mapping for LED/RGB Matrix max brightness ([#18403](https://github.com/qmk/qmk_firmware/pull/18403))
* Add DD mapping for LED/RGB Matrix split count ([#18408](https://github.com/qmk/qmk_firmware/pull/18408))
* Add DD mapping for LED/RGB Matrix HSVS steps ([#18414](https://github.com/qmk/qmk_firmware/pull/18414))
* Remove RGBLIGHT_ANIMTION and clean up effect defines for 0-F ([#18725](https://github.com/qmk/qmk_firmware/pull/18725))
* Merge API update workflow ([#19121](https://github.com/qmk/qmk_firmware/pull/19121))
Bugs:
* Fix layer switching from tap dances by redoing the keymap lookup ([#17935](https://github.com/qmk/qmk_firmware/pull/17935))
* ws2812: replace RGBLED_NUM with driver-owned constant to decouple driver from RGBLEDs/RGBMATRIX defines ([#18036](https://github.com/qmk/qmk_firmware/pull/18036))
* Prevent USB peripheral fault when restarting USB on WB32 MCUs ([#18058](https://github.com/qmk/qmk_firmware/pull/18058))
* Fix mouse report comparison failing on shared EP (fixes KB preventing sleep) ([#18060](https://github.com/qmk/qmk_firmware/pull/18060))
* Fix incorrect `bluetooth.driver` rules.mk mapping ([#18205](https://github.com/qmk/qmk_firmware/pull/18205))
* Adjust `EXTRAKEY_ENABLE` ifdefs for `send_extra()` ([#18249](https://github.com/qmk/qmk_firmware/pull/18249))
* Fix docs regarding cirque pinnacle attenuation ([#18279](https://github.com/qmk/qmk_firmware/pull/18279))
* Avoid repeated calls to rgblight_set() in tight succession when setting lighting layers ([#18338](https://github.com/qmk/qmk_firmware/pull/18338))
* Fix cirque tap from secondary side of split keyboard ([#18351](https://github.com/qmk/qmk_firmware/pull/18351))
* Fix EECONFIG_KEYMAP_UPPER_BYTE init ([#18394](https://github.com/qmk/qmk_firmware/pull/18394))
* Fix retain brightness when val is changed while a layer is active ([#18426](https://github.com/qmk/qmk_firmware/pull/18426))
* Update Chibios to latest 21.11.2 changes for RP2040 XIP deadlock mitigation ([#18428](https://github.com/qmk/qmk_firmware/pull/18428))
* Fix incorrect g_led_config generation ([#18431](https://github.com/qmk/qmk_firmware/pull/18431))
* Fix Per Key LED Indicator Callbacks ([#18450](https://github.com/qmk/qmk_firmware/pull/18450))
* Update chibios-contrib for RP2040 i2c fixes take 2 ([#18455](https://github.com/qmk/qmk_firmware/pull/18455))
* Fix comment of CM_QUES (Colemak question mark) ([#18557](https://github.com/qmk/qmk_firmware/pull/18557))
* ChibiOS: Fix USB bus disconnect handling ([#18566](https://github.com/qmk/qmk_firmware/pull/18566))
* Update ChibiOS-Contrib for USB IRQ and bus handling fixes ([#18574](https://github.com/qmk/qmk_firmware/pull/18574))
* RP2040: only clear RX FIFO for serial pio driver clear ([#18581](https://github.com/qmk/qmk_firmware/pull/18581))
* Fix ST7565 handler deadlock ([#18609](https://github.com/qmk/qmk_firmware/pull/18609))
* Fix/Update ChibiOS hardware ID ([#18613](https://github.com/qmk/qmk_firmware/pull/18613))
* Fix some rp2040 hardware ID errors ([#18617](https://github.com/qmk/qmk_firmware/pull/18617))
* Fix joystick functionality for ChibiOS and OTG (Blackpill) ([#18631](https://github.com/qmk/qmk_firmware/pull/18631))
* fix typo in solenoid.h ([#18635](https://github.com/qmk/qmk_firmware/pull/18635))
* Fix boundary in `RGB_MATRIX_INDICATOR_SET_COLOR` ([#18650](https://github.com/qmk/qmk_firmware/pull/18650))
* Fix MIDI output endpoint to use the out direction ([#18654](https://github.com/qmk/qmk_firmware/pull/18654))
* Fix mouse use within send_string ([#18659](https://github.com/qmk/qmk_firmware/pull/18659))
* Correctly build keymap.json containing additional config ([#18766](https://github.com/qmk/qmk_firmware/pull/18766))
* Correctly build out of tree keymap.json containing additional config ([#18775](https://github.com/qmk/qmk_firmware/pull/18775))
* Fix garbled test output ([#18822](https://github.com/qmk/qmk_firmware/pull/18822))
* Fix rgb_matrix_set_flags_noeeprom declaration ([#18860](https://github.com/qmk/qmk_firmware/pull/18860))
* Add missing Space Cadet alias ([#18876](https://github.com/qmk/qmk_firmware/pull/18876))
* Fix oled_render to render all dirty blocks. ([#18887](https://github.com/qmk/qmk_firmware/pull/18887))
* compiler.txt: ensure file exists before comparison ([#18921](https://github.com/qmk/qmk_firmware/pull/18921))
* Fix compilation issue with WPM ([#18965](https://github.com/qmk/qmk_firmware/pull/18965))
* Fix keycode parameter extraction to match the new DD keycodes ([#18977](https://github.com/qmk/qmk_firmware/pull/18977))
* Fix jump in mouse_report value when scale changes during cirque get report ([#18992](https://github.com/qmk/qmk_firmware/pull/18992))
* Fixup WS2812 vendor driver ([#19028](https://github.com/qmk/qmk_firmware/pull/19028))
* Add missing prototype for get_hold_on_other_key_press to resolve #18855 ([#19056](https://github.com/qmk/qmk_firmware/pull/19056))
* Fix duplicate key in keyboard.jsonschema ([#19058](https://github.com/qmk/qmk_firmware/pull/19058))
* Fixup `keyboard.jsonschema`. ([#19059](https://github.com/qmk/qmk_firmware/pull/19059))
* fixed MOUSEKEY_INERTIA on AVR ([#19096](https://github.com/qmk/qmk_firmware/pull/19096))
* Fix encoder_init call order in keyboard_init ([#19140](https://github.com/qmk/qmk_firmware/pull/19140))
* Fixup installation procedure for different Fedora versions. ([#19159](https://github.com/qmk/qmk_firmware/pull/19159))

367
docs/ChangeLog/20230226.md Normal file
View file

@ -0,0 +1,367 @@
# QMK Breaking Changes - 2023 February 26 Changelog
## Changes Requiring User Action :id=changes-requiring-user-action
### `IGNORE_MOD_TAP_INTERRUPT` behaviour changes ([#15741](https://github.com/qmk/qmk_firmware/pull/15741)) :id=i-m-t-i
`IGNORE_MOD_TAP_INTERRUPT_PER_KEY` has been removed and `IGNORE_MOD_TAP_INTERRUPT` deprecated as a stepping stone towards making `IGNORE_MOD_TAP_INTERRUPT` the new default behavior for mod-taps in the future.
In place of the now removed `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`, one must use the pre-existing `HOLD_ON_OTHER_KEY_PRESS` option.
In most cases, updating `get_ignore_mod_tap_interrupt` to `get_hold_on_other_key_press` is simply a matter of renaming the function and swapping every `true` by `false` and vice versa. The one subtlety you may need to look out for is that the `get_ignore_mod_tap_interrupt` was only ever called with mod-taps passed in as the `keycode` argument, while the `keycode` argument of `get_hold_on_other_key_press` can be any dual-role key. This includes not only mod-taps, but also layer-taps, one shot keys, `TT(layer)` and more. This has an impact on the effect of the `default` case in a typical per-key configuration making use of a `switch(keycode)` statement.
To illustrate, let's take the example of a configuration where we'd want all mod-taps to activate the modifier if another key is pressed while held with the exception of `LCTL_T(KC_A)`, which should ignore keys pressed while it is held and activate the modifier only if it has been held for longer than the tapping term. In addition, we would like to keep the default "ignore-interrupt" behavior of layer taps.
An old way to do this would be via the following code:
```c
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case LCTL_T(KC_A):
return true;
default:
return false;
}
}
```
The correct way to update this code without accidentally changing how the layer-taps work would be the following:
```c
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
// Capture all mod-tap keycodes.
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
if (keycode == LCTL_T(KC_A)) {
// Disable HOLD_ON_OTHER_KEY_PRESS for LCTL_T(KC_A)
// aka enable IGNORE_MOD_TAP_INTERRUPT for LCTL_T(KC_A).
return false;
} else {
// Enable HOLD_ON_OTHER_KEY_PRESS for every other mod-tap keycode.
return true;
}
default:
return false;
}
}
```
For more information, you are invited to read the sections on [IGNORE_MOD_TAP_INTERRUPT](tap_hold.md#ignore-mod-tap-interrupt) and [HOLD_ON_OTHER_KEY_PRESS](tap_hold.md#hold-on-other-key-press) in the page on [Tap-Hold configuration options](tap_hold.md).
### `TAPPING_FORCE_HOLD` => `QUICK_TAP_TERM` ([#17007](https://github.com/qmk/qmk_firmware/pull/17007)) :id=quick-tap-term
`TAPPING_FORCE_HOLD` feature is now replaced by `QUICK_TAP_TERM`. Instead of turning off auto-repeat completely, user will have the option to configure a `QUICK_TAP_TERM` in milliseconds. When the user holds a tap-hold key after tapping it within `QUICK_TAP_TERM`, QMK will send the tap keycode to the host, enabling auto-repeat.
Its value is set to `TAPPING_TERM` by default and it can be reduced to match typing habits to avoid false triggers. To disable auto-repeat completely, set `QUICK_TAP_TERM` to zero.
`TAPPING_FORCE_HOLD_PER_KEY` is also deprecated and replaced by `QUICK_TAP_TERM_PER_KEY`. The old granular control function for tapping force hold is:
```c
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LT(1, KC_BSPC):
return true;
default:
return false;
}
}
```
That function can be replaced with:
```c
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case SFT_T(KC_SPC):
return 0;
default:
return QUICK_TAP_TERM;
}
}
```
For more details, please read the updated documentation section on [Quick Tap Term](tap_hold.md#quick-tap-term).
### Leader Key Rework :id=leader-key-rework ([#19632](https://github.com/qmk/qmk_firmware/pull/19632))
The Leader Key feature API has been significantly improved, along with some bugfixes and added tests.
Instead of defining your leader sequences in `matrix_scan_user()`, they are now handled in the `leader_end_user()` callback, and the `LEADER_EXTERNS()`/`LEADER_DICTIONARY()` macros are no longer needed:
```c
void leader_end_user(void) {
if (leader_sequence_one_key(KC_F)) {
// Leader, f => Types the below string
SEND_STRING("QMK is awesome.");
} else if (leader_sequence_two_keys(KC_D, KC_D)) {
// Leader, d, d => Ctrl+A, Ctrl+C
SEND_STRING(SS_LCTL("a") SS_LCTL("c"));
} else if (leader_sequence_three_keys(KC_D, KC_D, KC_S)) {
// Leader, d, d, s => Types the below string
SEND_STRING("https://start.duckduckgo.com\n");
} else if (leader_sequence_two_keys(KC_A, KC_S)) {
// Leader, a, s => GUI+S
tap_code16(LGUI(KC_S));
}
}
```
For more information please see the [Leader Key documentation](feature_leader_key.md).
### Updated Keyboard Codebases :id=updated-keyboard-codebases
The following keyboards have had their source moved within QMK:
| Old Keyboard Name | New Keyboard Name |
|-----------------------------|--------------------------|
| ramonimbao/aelith | rmi_kb/aelith |
| ramonimbao/herringbone/pro | rmi_kb/herringbone/pro |
| ramonimbao/herringbone/v1 | rmi_kb/herringbone/v1 |
| ramonimbao/mona/v1_1 | rmi_kb/mona/v1_1 |
| ramonimbao/mona/v1 | rmi_kb/mona/v1 |
| ramonimbao/mona/v32a | rmi_kb/mona/v32a |
| ramonimbao/squishy65 | rmi_kb/squishy65 |
| ramonimbao/squishytkl | rmi_kb/squishytkl |
| ramonimbao/tkl_ff | rmi_kb/tkl_ff |
| ramonimbao/tkl_ff/v1 | rmi_kb/tkl_ff/v1 |
| ramonimbao/tkl_ff/v2 | rmi_kb/tkl_ff/v2 |
| ramonimbao/wete/v1 | rmi_kb/wete/v1 |
| ramonimbao/wete/v2 | rmi_kb/wete/v2 |
| the_uni | stenothe_uni |
| xelus/xs60 | xelus/xs60/soldered |
## Notable core changes :id=notable-core
As per last breaking changes cycle, there has been _a lot_ of emphasis on behind-the-scenes changes, mainly around consolidation of core subsystems and constant values, as well as addressing tech debt. Whilst not outwardly visible, this cleanup and refactoring should start paying dividends as it simplifies future development and maintenance.
A handful of examples:
* Standardised the lower/raise/adjust layer change pattern with explicit keycodes and configurable target layers
* Cleaned up a lot of Makefile logic to simplify and speed up builds
* Automated tooling to regenerate keycode values has been hooked into the PR pipeline and will trigger failures if they're incorrect
* Many more configuration options have moved into `info.json`, such as backlight, encoders
* Additional unit tests to ensure keycode behaviours don't accidentally change
## Full changelist :id=full-changelist
Core:
* Remove IGNORE_MOD_TAP_INTERRUPT_PER_KEY in favour of HOLD_ON_OTHER_KEY_PRESS_PER_KEY ([#15741](https://github.com/qmk/qmk_firmware/pull/15741))
* Add combo hook to allow per layer combo reference layers. ([#16699](https://github.com/qmk/qmk_firmware/pull/16699))
* Replace Tapping Force Hold feature with Quick Tap Term ([#17007](https://github.com/qmk/qmk_firmware/pull/17007))
* [Test] Reset timer for every unit test and provide timestamps for log messages ([#17028](https://github.com/qmk/qmk_firmware/pull/17028))
* Bug17281 - Retain momentary layers until the end of tapping ([#17282](https://github.com/qmk/qmk_firmware/pull/17282))
* Detect host OS based on USB fingerprint ([#18463](https://github.com/qmk/qmk_firmware/pull/18463))
* allow locking the matrix state ([#18852](https://github.com/qmk/qmk_firmware/pull/18852))
* Initial DD keymap_extras migration ([#19031](https://github.com/qmk/qmk_firmware/pull/19031))
* Support inverted scan logic for optical switches ([#19053](https://github.com/qmk/qmk_firmware/pull/19053))
* Corrections to uart driver for Chibios platform ([#19075](https://github.com/qmk/qmk_firmware/pull/19075))
* Remaining DD keymap_extras migration ([#19110](https://github.com/qmk/qmk_firmware/pull/19110))
* Add udev rule for the WB32 DFU bootloader ([#19135](https://github.com/qmk/qmk_firmware/pull/19135))
* Add Michi MCU Converter support ([#19163](https://github.com/qmk/qmk_firmware/pull/19163))
* Add Split support for Haptic feedback ([#19203](https://github.com/qmk/qmk_firmware/pull/19203))
* Allow mod-tap hold action on one shot layer ([#19214](https://github.com/qmk/qmk_firmware/pull/19214))
* Remove RGBLIGHT_ANIMATIONS from core (+cleanup) ([#19216](https://github.com/qmk/qmk_firmware/pull/19216))
* Revert WB32 ISO workaround ([#19224](https://github.com/qmk/qmk_firmware/pull/19224))
* Prevent dynamic keymaps from processing layers that don't exist ([#19225](https://github.com/qmk/qmk_firmware/pull/19225))
* Add `*_RIGHT` configuration for PMW33XX driver ([#19243](https://github.com/qmk/qmk_firmware/pull/19243))
* Remove deprecated led_set_kb ([#19273](https://github.com/qmk/qmk_firmware/pull/19273))
* Tests that caps word stays active after use of OSL ([#19303](https://github.com/qmk/qmk_firmware/pull/19303))
* Allow overriding of keymap/encodermap layer count. ([#19325](https://github.com/qmk/qmk_firmware/pull/19325))
* guard action related debug messages ([#19348](https://github.com/qmk/qmk_firmware/pull/19348))
* use `IS_EVENT` macro instead of `!IS_NOEVENT` ([#19366](https://github.com/qmk/qmk_firmware/pull/19366))
* [Test] Introduce VERIFY_AND_CLEAR shorthand ([#19370](https://github.com/qmk/qmk_firmware/pull/19370))
* Add RGB565 and RGB888 color support to Quantum Painter ([#19382](https://github.com/qmk/qmk_firmware/pull/19382))
* Initial DD keycode regen workflow ([#19400](https://github.com/qmk/qmk_firmware/pull/19400))
* Update RGB matrix reactive gradient timer scale ([#19415](https://github.com/qmk/qmk_firmware/pull/19415))
* De-obfuscate random8 functions ([#19416](https://github.com/qmk/qmk_firmware/pull/19416))
* Use random8 for jellybean effect ([#19418](https://github.com/qmk/qmk_firmware/pull/19418))
* Align definition of unicode_map ([#19452](https://github.com/qmk/qmk_firmware/pull/19452))
* Add analog support for RP2040 ([#19453](https://github.com/qmk/qmk_firmware/pull/19453))
* [CI] Regenerate Files ([#19463](https://github.com/qmk/qmk_firmware/pull/19463))
* Build warning when not valid work-tree ([#19475](https://github.com/qmk/qmk_firmware/pull/19475))
* Migrate 'make git-submodule' to CLI command ([#19479](https://github.com/qmk/qmk_firmware/pull/19479))
* Remove cmp checks from Makefile ([#19480](https://github.com/qmk/qmk_firmware/pull/19480))
* Replace list_keyboards.sh with CLI calls ([#19485](https://github.com/qmk/qmk_firmware/pull/19485))
* Remove unused Makefile paths ([#19487](https://github.com/qmk/qmk_firmware/pull/19487))
* Migrate submodule dirty check to CLI ([#19488](https://github.com/qmk/qmk_firmware/pull/19488))
* Remove `make all-<platform>` build targets ([#19496](https://github.com/qmk/qmk_firmware/pull/19496))
* Relax converter validation within keymap schema ([#19544](https://github.com/qmk/qmk_firmware/pull/19544))
* De-duplicate platform detection ([#19545](https://github.com/qmk/qmk_firmware/pull/19545))
* Add alias support for converters ([#19563](https://github.com/qmk/qmk_firmware/pull/19563))
* Revert "De-duplicate platform detection" ([#19564](https://github.com/qmk/qmk_firmware/pull/19564))
* Add mmoskal/uf2-stm32f103 bootloader support ([#19594](https://github.com/qmk/qmk_firmware/pull/19594))
* usb_main.c: remove `CH_KERNEL_MAJOR` check ([#19597](https://github.com/qmk/qmk_firmware/pull/19597))
* Use the correct keycode when updating WPM ([#19599](https://github.com/qmk/qmk_firmware/pull/19599))
* De-duplicate platform detection ([#19603](https://github.com/qmk/qmk_firmware/pull/19603))
* Refactor rain pixel function ([#19606](https://github.com/qmk/qmk_firmware/pull/19606))
* ChibiOS: Consolidate report sending code ([#19607](https://github.com/qmk/qmk_firmware/pull/19607))
* Add f303 to tinyuf2 bootloader support ([#19620](https://github.com/qmk/qmk_firmware/pull/19620))
* Refactor Leader key feature ([#19632](https://github.com/qmk/qmk_firmware/pull/19632))
* Split out mcu_selection to platform ([#19701](https://github.com/qmk/qmk_firmware/pull/19701))
* Move MIDI code out of tmk_core ([#19704](https://github.com/qmk/qmk_firmware/pull/19704))
* Remove deprecated Quantum keycodes ([#19712](https://github.com/qmk/qmk_firmware/pull/19712))
* QP: Correct rotation and offset when using LVGL ([#19713](https://github.com/qmk/qmk_firmware/pull/19713))
* Remove usages of config_common.h from config.h files. ([#19714](https://github.com/qmk/qmk_firmware/pull/19714))
* Relocate diode direction definitions ([#19715](https://github.com/qmk/qmk_firmware/pull/19715))
* Normalise Swap Hands keycodes ([#19720](https://github.com/qmk/qmk_firmware/pull/19720))
* Strip out more of config_common ([#19722](https://github.com/qmk/qmk_firmware/pull/19722))
* Remove `IS_HOST_LED_ON` and migrate usages ([#19753](https://github.com/qmk/qmk_firmware/pull/19753))
* Move more unicode ranges to DD ([#19755](https://github.com/qmk/qmk_firmware/pull/19755))
* Tidy up use of keycode range helpers ([#19756](https://github.com/qmk/qmk_firmware/pull/19756))
* Tri Layer Keys ([#19795](https://github.com/qmk/qmk_firmware/pull/19795))
* Remove matrix_init_quantum/matrix_scan_quantum ([#19806](https://github.com/qmk/qmk_firmware/pull/19806))
* Tidy up use of keycode range helpers ([#19813](https://github.com/qmk/qmk_firmware/pull/19813))
* Remove `config.h` include from quantum files ([#19817](https://github.com/qmk/qmk_firmware/pull/19817))
* Add rp2040_ce and add elite-pi and helios as alias ([#19830](https://github.com/qmk/qmk_firmware/pull/19830))
* Add swap hands status function ([#19831](https://github.com/qmk/qmk_firmware/pull/19831))
* Align sequencer keycodes ([#19875](https://github.com/qmk/qmk_firmware/pull/19875))
* Align magic keycodes ([#19877](https://github.com/qmk/qmk_firmware/pull/19877))
* Move `KC_MISSION_CONTROL`/`KC_LAUNCHPAD` keycodes to core ([#19884](https://github.com/qmk/qmk_firmware/pull/19884))
* Reallocate user/kb keycode ranges ([#19907](https://github.com/qmk/qmk_firmware/pull/19907))
* Reallocate SAFE_RANGE ([#19909](https://github.com/qmk/qmk_firmware/pull/19909))
* Hide hex output when building uf2 ([#19940](https://github.com/qmk/qmk_firmware/pull/19940))
CLI:
* Automate "Data Driven" migrations? ([#17820](https://github.com/qmk/qmk_firmware/pull/17820))
* Generate encodermap output from keymap.json. ([#18915](https://github.com/qmk/qmk_firmware/pull/18915))
* Publish keymap.json to API ([#19167](https://github.com/qmk/qmk_firmware/pull/19167))
* Apply suggested workaround for #18371 ([#19226](https://github.com/qmk/qmk_firmware/pull/19226))
* Align new-keymap with new-keyboard ([#19229](https://github.com/qmk/qmk_firmware/pull/19229))
* Validate keyboard name before accepting further input ([#19394](https://github.com/qmk/qmk_firmware/pull/19394))
* Implement XAP style merge semantics for DD keycodes ([#19397](https://github.com/qmk/qmk_firmware/pull/19397))
* Allow CLI to flash .uf2 files ([#19462](https://github.com/qmk/qmk_firmware/pull/19462))
* Report submodule status when not valid work-tree ([#19474](https://github.com/qmk/qmk_firmware/pull/19474))
* `qmk compile`/`qmk flash` - Validate keymap argument ([#19530](https://github.com/qmk/qmk_firmware/pull/19530))
* Add commit info to `version.h` ([#19542](https://github.com/qmk/qmk_firmware/pull/19542))
* Remove CLI commands: `multibuild`, `cformat`, `fileformat`, `pyformat`. ([#19629](https://github.com/qmk/qmk_firmware/pull/19629))
* Print distro in doctor output ([#19633](https://github.com/qmk/qmk_firmware/pull/19633))
* Reduce false positives in layout name validation ([#19646](https://github.com/qmk/qmk_firmware/pull/19646))
* Add `mass-compile` ability to filter by key existence. ([#19885](https://github.com/qmk/qmk_firmware/pull/19885))
Submodule updates:
* Update ChibiOS[-Contrib], SIO driver, configs ([#17915](https://github.com/qmk/qmk_firmware/pull/17915))
* Quantum Painter - LVGL Integration ([#18499](https://github.com/qmk/qmk_firmware/pull/18499))
* [RP2040] update i2c drivers to reflect peripheral number ([#19277](https://github.com/qmk/qmk_firmware/pull/19277))
* Update pico-sdk to 1.5.0 ([#19829](https://github.com/qmk/qmk_firmware/pull/19829))
Keyboards:
* Refactor entire Handwired K552 keyboard ([#18066](https://github.com/qmk/qmk_firmware/pull/18066))
* Moonlander: Add RGB LED layout map macro ([#18745](https://github.com/qmk/qmk_firmware/pull/18745))
* Add the Ortho60 v2 Keyboard to QMK ([#18890](https://github.com/qmk/qmk_firmware/pull/18890))
* Refactor xs60 with soldered and hotswap version ([#19049](https://github.com/qmk/qmk_firmware/pull/19049))
* [GMMK Pro] Change DEBOUNCE_TYPE to sym_eager_pk to reduce latency ([#19153](https://github.com/qmk/qmk_firmware/pull/19153))
* Add KPrepublic BM16A v2 ([#19194](https://github.com/qmk/qmk_firmware/pull/19194))
* Add Rama Works M60-B ([#19248](https://github.com/qmk/qmk_firmware/pull/19248))
* Revert RESET-> QK_BOOT in Read Me files where applicable ([#19262](https://github.com/qmk/qmk_firmware/pull/19262))
* Remove broken keymap/userspace ([#19271](https://github.com/qmk/qmk_firmware/pull/19271))
* The Uni change folder location ([#19326](https://github.com/qmk/qmk_firmware/pull/19326))
* New keymap for ID75 - paryz ([#19350](https://github.com/qmk/qmk_firmware/pull/19350))
* Remove useless line continuations ([#19399](https://github.com/qmk/qmk_firmware/pull/19399))
* Add The Uni Utility Belt Keymap ([#19411](https://github.com/qmk/qmk_firmware/pull/19411))
* Migrate `MCU` and `BOOTLOADER` to data-driven ([#19529](https://github.com/qmk/qmk_firmware/pull/19529))
* Migrate `LAYOUTS` to data driven ([#19541](https://github.com/qmk/qmk_firmware/pull/19541))
* Tidy up use of CTPC ([#19570](https://github.com/qmk/qmk_firmware/pull/19570))
* Remove matrix size defines ([#19581](https://github.com/qmk/qmk_firmware/pull/19581))
* keebio/iris document LED matrix ([#19588](https://github.com/qmk/qmk_firmware/pull/19588))
* Add support for current/voltage measurement on Ghoul. ([#19630](https://github.com/qmk/qmk_firmware/pull/19630))
* Rename ramonimbao folder to rmi_kb ([#19699](https://github.com/qmk/qmk_firmware/pull/19699))
* Remove commented out backlight config & stray "backlight levels" ([#19703](https://github.com/qmk/qmk_firmware/pull/19703))
* Clean up Force NKRO in config.h ([#19718](https://github.com/qmk/qmk_firmware/pull/19718))
* Remove unused `MATRIX_HAS_GHOST` from config.h ([#19726](https://github.com/qmk/qmk_firmware/pull/19726))
* Debounce defines cleanup ([#19742](https://github.com/qmk/qmk_firmware/pull/19742))
* Remove unused `LOCKING_SUPPORT_ENABLE` from config.h ([#19748](https://github.com/qmk/qmk_firmware/pull/19748))
* Remove `DEBOUNCE` macro usage ([#19750](https://github.com/qmk/qmk_firmware/pull/19750))
* Remove unused `GRAVE_ESC_CTRL_OVERRIDE` from config.h ([#19752](https://github.com/qmk/qmk_firmware/pull/19752))
* Remove unused Bootmagic row/col defines from config.h ([#19761](https://github.com/qmk/qmk_firmware/pull/19761))
* Remove unused `SOFT_SERIAL_PIN` from config.h ([#19768](https://github.com/qmk/qmk_firmware/pull/19768))
* Remove `SOFT_SERIAL_PIN` for non-split boards ([#19774](https://github.com/qmk/qmk_firmware/pull/19774))
* implement missing layouts + DD migration for wilba_tech/wt60_d ([#19777](https://github.com/qmk/qmk_firmware/pull/19777))
* Move LED indicator config to data driven ([#19800](https://github.com/qmk/qmk_firmware/pull/19800))
* Migrate `DIRECT_PINS` to data driven ([#19826](https://github.com/qmk/qmk_firmware/pull/19826))
* Remove lingering `I2CD2` usages w/ RP2040 ([#19833](https://github.com/qmk/qmk_firmware/pull/19833))
* Brick ([#19851](https://github.com/qmk/qmk_firmware/pull/19851))
* Remove unused RGBLight defines from config.h ([#19859](https://github.com/qmk/qmk_firmware/pull/19859))
* Move Bootmagic config to data driven ([#19860](https://github.com/qmk/qmk_firmware/pull/19860))
* Move `SOFT_SERIAL_PIN` to data driven ([#19863](https://github.com/qmk/qmk_firmware/pull/19863))
* Move layouts for direct_pins boards to data driven ([#19872](https://github.com/qmk/qmk_firmware/pull/19872))
* Move QMK LUFA bootloader config to data driven ([#19879](https://github.com/qmk/qmk_firmware/pull/19879))
* Move backlight config to data driven, part 1 ([#19887](https://github.com/qmk/qmk_firmware/pull/19887))
* Add license headers to all default layout keymaps ([#19888](https://github.com/qmk/qmk_firmware/pull/19888))
* Migrate some more layouts to data driven ([#19889](https://github.com/qmk/qmk_firmware/pull/19889))
* Remove magic bodges from via keymaps ([#19890](https://github.com/qmk/qmk_firmware/pull/19890))
* Refactor more `KC_MISSION_CONTROL`/`KC_LAUNCHPAD` usages ([#19891](https://github.com/qmk/qmk_firmware/pull/19891))
* Remove default and unused `BACKLIGHT_LEVELS` ([#19898](https://github.com/qmk/qmk_firmware/pull/19898))
* Move backlight config to data driven ([#19910](https://github.com/qmk/qmk_firmware/pull/19910))
* Remove VIA specific use of `MACRO0*` ([#19918](https://github.com/qmk/qmk_firmware/pull/19918))
* Use standard magic keycodes in `yandrstudio` keymaps ([#19919](https://github.com/qmk/qmk_firmware/pull/19919))
* Move encoder config to data driven ([#19923](https://github.com/qmk/qmk_firmware/pull/19923))
Keyboard fixes:
* Partially revert #18940 for Ploopy Thumb Trackball ([#18943](https://github.com/qmk/qmk_firmware/pull/18943))
* Fix up Info.Json files that weren't parsing correctly ([#19275](https://github.com/qmk/qmk_firmware/pull/19275))
* Fix DZTECH Tofu II v1 i2c config ([#19306](https://github.com/qmk/qmk_firmware/pull/19306))
* Fixup build failures. ([#19332](https://github.com/qmk/qmk_firmware/pull/19332))
* Fixup horrortroll/handwired_k552 ([#19447](https://github.com/qmk/qmk_firmware/pull/19447))
* Ignore defaults.hjson values if already set ([#19511](https://github.com/qmk/qmk_firmware/pull/19511))
* Fix mk0_avr_extra PIN_COMPATIBLE lint warning ([#19640](https://github.com/qmk/qmk_firmware/pull/19640))
* fix pegasushoof caps light, add via keymap ([#19649](https://github.com/qmk/qmk_firmware/pull/19649))
* Fixup handwired/jscotto/scotto40 ([#19675](https://github.com/qmk/qmk_firmware/pull/19675))
* Clean up remaining rules.mk `MCU`/`BOOTLOADER`s ([#19778](https://github.com/qmk/qmk_firmware/pull/19778))
* Fix errors flagged by generate-api ([#19784](https://github.com/qmk/qmk_firmware/pull/19784))
* Fix merge error with fave84 board ([#19808](https://github.com/qmk/qmk_firmware/pull/19808))
* Fixup ek65 -- add processor & bootloader in `info.json` ([#19815](https://github.com/qmk/qmk_firmware/pull/19815))
* Fixup durgod/dgk6x (scroll lock mis-defined as num lock) ([#19864](https://github.com/qmk/qmk_firmware/pull/19864))
* Fix API generation ([#19866](https://github.com/qmk/qmk_firmware/pull/19866))
* Fixup for_science ([#19867](https://github.com/qmk/qmk_firmware/pull/19867))
* Fix more build failures ([#19869](https://github.com/qmk/qmk_firmware/pull/19869))
* Fixup pegasushoof VIA keymap ([#19874](https://github.com/qmk/qmk_firmware/pull/19874))
* Fixup cannonkeys/satisfaction75 (readd `backlight.breathing_period`) ([#19901](https://github.com/qmk/qmk_firmware/pull/19901))
* Add some missing `#pragma once`s ([#19902](https://github.com/qmk/qmk_firmware/pull/19902))
* `keebio/kbo5000`: fix encoder config ([#19941](https://github.com/qmk/qmk_firmware/pull/19941))
Others:
* KC_GESC -> QK_GESC for cn and ja Docs ([#19024](https://github.com/qmk/qmk_firmware/pull/19024))
* Update files changed action ([#19172](https://github.com/qmk/qmk_firmware/pull/19172))
* DD bootmagic config ([#19201](https://github.com/qmk/qmk_firmware/pull/19201))
* Rework input_pressed_state docs ([#19267](https://github.com/qmk/qmk_firmware/pull/19267))
* Change log for Quick Tap Term ([#19341](https://github.com/qmk/qmk_firmware/pull/19341))
* Promote CTPC warning to error ([#19565](https://github.com/qmk/qmk_firmware/pull/19565))
* Run format-text on keyboard PRs ([#19656](https://github.com/qmk/qmk_firmware/pull/19656))
* Change defines by enums ([#19793](https://github.com/qmk/qmk_firmware/pull/19793))
* [Doc]Remove depracted extension links in vscode guide ([#19842](https://github.com/qmk/qmk_firmware/pull/19842))
Bugs:
* Make Magic handling more consistent in Action Keycode handling ([#9126](https://github.com/qmk/qmk_firmware/pull/9126))
* Fix functions when `NO_ACTION_TAPPING` is defined ([#11528](https://github.com/qmk/qmk_firmware/pull/11528))
* Return USB HID GET_REPORT requests ([#14814](https://github.com/qmk/qmk_firmware/pull/14814))
* Fixed NKRO issue caused by HID_SET_PROTOCOL on Chibios platform ([#17588](https://github.com/qmk/qmk_firmware/pull/17588))
* kint36: do not restart USB stack after wakeup ([#19077](https://github.com/qmk/qmk_firmware/pull/19077))
* Fixes to source generation [mostly typographic] ([#19160](https://github.com/qmk/qmk_firmware/pull/19160))
* Teensy 3.5: do not restart USB stack after wakeup ([#19269](https://github.com/qmk/qmk_firmware/pull/19269))
* Fixing PMW3389.c so it can compile ([#19301](https://github.com/qmk/qmk_firmware/pull/19301))
* UCIS: remove `qk_` prefix ([#19302](https://github.com/qmk/qmk_firmware/pull/19302))
* Leader: remove `qk_` prefix ([#19304](https://github.com/qmk/qmk_firmware/pull/19304))
* Tap Dance: remove `qk_` prefix ([#19313](https://github.com/qmk/qmk_firmware/pull/19313))
* Revert changes to keymap_steno.h ([#19412](https://github.com/qmk/qmk_firmware/pull/19412))
* Use unique name for regen PR branches ([#19464](https://github.com/qmk/qmk_firmware/pull/19464))
* Restore packing of midi note keycodes ([#19468](https://github.com/qmk/qmk_firmware/pull/19468))
* Fix 'Need at least one layout defined in info.json' check ([#19537](https://github.com/qmk/qmk_firmware/pull/19537))
* `qmk doctor` - Handle permission issues while checking udev ([#19548](https://github.com/qmk/qmk_firmware/pull/19548))
* `qmk doctor` - Handle timeouts while checking binaries ([#19549](https://github.com/qmk/qmk_firmware/pull/19549))
* Fix CLI community detection ([#19562](https://github.com/qmk/qmk_firmware/pull/19562))
* Fix joystick build for ChibiOS ([#19602](https://github.com/qmk/qmk_firmware/pull/19602))
* Fix converter alias after 19603 ([#19644](https://github.com/qmk/qmk_firmware/pull/19644))
* Fix functions with empty params ([#19647](https://github.com/qmk/qmk_firmware/pull/19647))
* rp2040: fix timer wrap deadlock in ws2812 vendor driver ([#19652](https://github.com/qmk/qmk_firmware/pull/19652))
* analog.c: Fix `pinToMux()` for STM32F0xx ([#19658](https://github.com/qmk/qmk_firmware/pull/19658))
* Fix quantum ring_buffer for ChibiOS ([#19683](https://github.com/qmk/qmk_firmware/pull/19683))
* Regen keycode_table for unit tests ([#19721](https://github.com/qmk/qmk_firmware/pull/19721))
* Fix midi after recent refactoring ([#19723](https://github.com/qmk/qmk_firmware/pull/19723))
* Fix build failures with `OPT = 0` due to inline functions ([#19767](https://github.com/qmk/qmk_firmware/pull/19767))
* Fix tri layer compiler issue if NO_ACTION_LAYER is defined ([#19821](https://github.com/qmk/qmk_firmware/pull/19821))
* Fixup `develop` compiles. ([#19828](https://github.com/qmk/qmk_firmware/pull/19828))
* Fix Layer Mod mishandling of right-handed mods, a mixup of 5-bit vs. 8-bit mods representation. ([#19845](https://github.com/qmk/qmk_firmware/pull/19845))
* Fix compilation issue for Key Overrides ([#19856](https://github.com/qmk/qmk_firmware/pull/19856))
* Fix regen script for macOS ([#19857](https://github.com/qmk/qmk_firmware/pull/19857))
* Fix compilation error when defining QUICK_TAP_TERM_PER_KEY ([#19893](https://github.com/qmk/qmk_firmware/pull/19893))
* VIA Protocol 12 + fixes ([#19916](https://github.com/qmk/qmk_firmware/pull/19916))

View file

@ -76,13 +76,16 @@
* Software Features
* [Auto Shift](feature_auto_shift.md)
* [Autocorrect](feature_autocorrect.md)
* [Caps Word](feature_caps_word.md)
* [Combos](feature_combo.md)
* [Debounce API](feature_debounce_type.md)
* [EEPROM](feature_eeprom.md)
* [Key Lock](feature_key_lock.md)
* [Key Overrides](feature_key_overrides.md)
* [Layers](feature_layers.md)
* [One Shot Keys](one_shot_keys.md)
* [OS Detection](feature_os_detection.md)
* [Raw HID](feature_rawhid.md)
* [Secure](feature_secure.md)
* [Send String](feature_send_string.md)
@ -90,6 +93,7 @@
* [Swap Hands](feature_swap_hands.md)
* [Tap Dance](feature_tap_dance.md)
* [Tap-Hold Configuration](tap_hold.md)
* [Tri Layer](feature_tri_layer.md)
* [Unicode](feature_unicode.md)
* [Userspace](feature_userspace.md)
* [WPM Calculation](feature_wpm.md)
@ -97,6 +101,7 @@
* Hardware Features
* Displays
* [Quantum Painter](quantum_painter.md)
* [Quantum Painter LVGL Integration](quantum_painter_lvgl.md)
* [HD44780 LCD Driver](feature_hd44780.md)
* [ST7565 LCD Driver](feature_st7565.md)
* [OLED Driver](feature_oled_driver.md)
@ -121,7 +126,6 @@
* [PS/2 Mouse](feature_ps2_mouse.md)
* [Split Keyboard](feature_split_keyboard.md)
* [Stenography](feature_stenography.md)
* [Thermal Printer](feature_thermal_printer.md)
* [Velocikey](feature_velocikey.md)
* Keyboard Building
@ -135,7 +139,7 @@
* Breaking Changes
* [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
* [Most Recent ChangeLog](ChangeLog/20220827.md "QMK v0.18.0 - 2022 Aug 27")
* [Most Recent ChangeLog](ChangeLog/20230226.md "QMK v0.20.0 - 2023 Feb 26")
* [Past Breaking Changes](breaking_changes_history.md)
* C Development
@ -170,7 +174,7 @@
* [Early initialization](platformdev_chibios_earlyinit.md)
* [Raspberry Pi RP2040](platformdev_rp2040.md)
* [Proton C](platformdev_proton_c.md)
* [WeAct Blackpill F411](platformdev_blackpill_f411.md)
* [WeAct Blackpill F4x1](platformdev_blackpill_f4x1.md)
* QMK Reference
* [Contributing to QMK](contributing.md)

View file

@ -43,6 +43,8 @@ Then place this include at the top of your code:
### ARM
#### STM32
Note that some of these pins are doubled-up on ADCs with the same channel. This is because the pins can be used for either ADC.
Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-indexed, whereas the F3 has 4 ADCs and the channels are 1-indexed. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation.
@ -121,6 +123,21 @@ Also note that the F0 and F3 use different numbering schemes. The F0 has a singl
<sup>² Not all STM32F4xx devices have ADC2 and/or ADC3, therefore some configurations shown in this table may be unavailable; in particular, pins `F4``F10` cannot be used as ADC inputs on devices which do not have ADC3. Check the device datasheet to confirm which pin functions are supported.</sup>
#### RP2040
RP2040 has only a single ADC (`ADCD1` in ChibiOS); in the QMK API the index for that ADC is 0.
|Channel|Pin |
|-------|-------------------|
|0 |`GP26` |
|1 |`GP27` |
|2 |`GP28` |
|3 |`GP29` |
|4 |Temperature sensor*|
<sup>* The temperature sensor is disabled by default and needs to be enabled by the RP2040-specific function: `adcRPEnableTS(&ADCD1)`. The ADC must be initialized before calling that function; an easy way to ensure that is to perform a dummy conversion.</sup>
## Functions
### AVR

View file

@ -14,14 +14,14 @@ This service is an asynchronous API for compiling custom keymaps. You POST some
"keymap": "my_awesome_keymap",
"layout": "LAYOUT_all",
"layers": [
["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_RO","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_MHEN","KC_SPC","KC_SPC","KC_HENK","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"],
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SLCK","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","RESET","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_INT1","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_INT5","KC_SPC","KC_SPC","KC_INT4","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"],
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SCRL","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","QK_BOOT","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
]
}
```
As you can see the payload describes all aspects of a keyboard necessary to create and generate a firmware. Each layer is a single list of QMK keycodes the same length as the keyboard's `LAYOUT` macro. If a keyboard supports mulitple `LAYOUT` macros you can specify which macro to use.
As you can see the payload describes all aspects of a keyboard necessary to create and generate a firmware. Each layer is a single list of QMK keycodes the same length as the keyboard's `LAYOUT` macro. If a keyboard supports multiple `LAYOUT` macros you can specify which macro to use.
## Submitting a Compile Job
@ -66,3 +66,41 @@ Once your compile job has finished you'll check the `result` key. The value of t
* `firmware_keymap_url`: A list of URLs for the `keymap.c`
* `firmware_source_url`: A list of URLs for the full firmware source code
* `output`: The stdout and stderr for this compile job. Errors will be found here.
## Constants :id=qmk-constants
If you're writing a tool that leverages constants used within QMK, the API is used to publish "locked-in" versions of those constants in order to ensure that any third-party tooling has a canonical set of information to work with.
The list of available constants can be retrieved by accessing one of the following endpoints:
```
$ curl https://keyboards.qmk.fm/v1/constants_metadata.json # For `master`
{"last_updated": "2022-11-26 00:00:00 GMT", "constants": {"keycodes": ["0.0.1"]}}
$ curl https://keyboards.develop.qmk.fm/v1/constants_metadata.json # For `develop`
{"last_updated": "2022-11-26 12:00:00 GMT", "constants": {"keycodes": ["0.0.1", "0.0.2"]}}
```
!> Versions exported by the `master` endpoint are locked-in. Any extra versions that exist on the `develop` endpoint which don't exist in `master` are subject to change.
?> Only keycodes are currently published, but over time all other "externally visible" IDs are expected to appear on these endpoints.
To retrieve the constants associated with a subsystem, the endpoint format is as follows:
```
# https://keyboards.qmk.fm/v1/constants/{subsystem}_{version}.json
```
Which, for the metadata endpoint above results in a request of:
```
$ curl https://keyboards.qmk.fm/v1/constants/keycodes_0.0.1.json
{
"ranges": {
"0x0000/0x00FF": {
"define": "QK_BASIC"
},
"0x0100/0x1EFF": {
"define": "QK_MODS"
},
"0x2000/0x1FFF": {
"define": "QK_MOD_TAP"
<snip>
```

View file

@ -159,7 +159,6 @@ A configuration example for the STM32F103C8 would be:
//halconf.h:
#define HAL_USE_PWM TRUE
#define HAL_USE_PAL TRUE
#define HAL_USE_GPT TRUE
#include_next <halconf.h>
```
@ -168,8 +167,6 @@ A configuration example for the STM32F103C8 would be:
#include_next <mcuconf.h>
#undef STM32_PWM_USE_TIM1
#define STM32_PWM_USE_TIM1 TRUE
#undef STM32_GPT_USE_TIM4
#define STM32_GPT_USE_TIM4 TRUE
```
If we now target pin A8, looking through the data-sheet of the STM32F103C8, for the timers and alternate functions
@ -184,7 +181,6 @@ with all this information, the configuration would contain these lines:
#define AUDIO_PIN A8
#define AUDIO_PWM_DRIVER PWMD1
#define AUDIO_PWM_CHANNEL 1
#define AUDIO_STATE_TIMER GPTD4
```
ChibiOS uses GPIOv1 for the F103, which only knows of one alternate function.
@ -207,15 +203,15 @@ You can also change the timer used for software PWM by defining the driver. For
While not an exhaustive list, the following table provides the scenarios that have been partially validated:
| | DAC basic | DAC additive | PWM hardware | PWM software |
|--------------------------|--------------------|--------------------|--------------------|--------------------|
| | DAC basic | DAC additive | PWM hardware | PWM software |
| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ |
| Atmega32U4 | :o: | :o: | :heavy_check_mark: | :o: |
| RP2040 | :x: | :x: | :heavy_check_mark: | ? |
| STM32F103C8 (bluepill) | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: |
| STM32F303CCT6 (proton-c) | :heavy_check_mark: | :heavy_check_mark: | ? | :heavy_check_mark: |
| STM32F405VG | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| L0xx | :x: (no Tim8) | ? | ? | ? |
:heavy_check_mark: : works and was tested
:o: : does not apply
:x: : not supported by MCU

View file

@ -4,49 +4,54 @@ This document describes QMK's Breaking Change process. A Breaking Change is any
This also includes any keyboard moves within the repository.
The breaking change period is when we will merge PR's that change QMK in dangerous or unexpected ways. There is a built-in period of testing so we are confident that any problems caused are rare or unable to be predicted.
The breaking change period is when we will merge PRs that change QMK in dangerous or unexpected ways. There is a built-in period of testing so we are confident that any problems caused are rare or unable to be predicted.
Practically, this means QMK merges the `develop` branch into the `master` branch on a 3-month cadence.
## What has been included in past Breaking Changes?
* [2023 Feb 26](ChangeLog/20230226.md)
* [2022 Nov 26](ChangeLog/20221126.md)
* [2022 Aug 27](ChangeLog/20220827.md)
* [2022 May 28](ChangeLog/20220528.md)
* [2022 Feb 26](ChangeLog/20220226.md)
* [2021 Nov 27](ChangeLog/20211127.md)
* [2021 Aug 28](ChangeLog/20210828.md)
* [2021 May 29](ChangeLog/20210529.md)
* [2021 Feb 27](ChangeLog/20210227.md)
* [2020 Nov 28](ChangeLog/20201128.md)
* [2020 Aug 29](ChangeLog/20200829.md)
* [2020 May 30](ChangeLog/20200530.md)
* [2020 Feb 29](ChangeLog/20200229.md)
* [2019 Aug 30](ChangeLog/20190830.md)
* [Older Breaking Changes](breaking_changes_history.md)
## When is the next Breaking Change?
The next Breaking Change is scheduled for November 26, 2022.
The next Breaking Change is scheduled for May 28, 2023.
### Important Dates
* 2022 Aug 27 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2022 Oct 29 - `develop` closed to new PR's.
* 2022 Oct 29 - Call for testers.
* 2022 Nov 12 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2022 Nov 19 - `develop` is locked, only critical bugfix PR's merged.
* 2022 Nov 24 - `master` is locked, no PR's merged.
* 2022 Nov 26 - Merge `develop` to `master`.
* 2022 Nov 26 - `master` is unlocked. PR's can be merged again.
* 2023 Feb 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2023 Apr 30 - `develop` closed to new PRs.
* 2023 Apr 30 - Call for testers.
* 2023 May 14 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2023 May 21 - `develop` is locked, only critical bugfix PRs merged.
* 2023 May 26 - `master` is locked, no PRs merged.
* 2023 May 28 - Merge `develop` to `master`.
* 2023 May 28 - `master` is unlocked. PRs can be merged again.
## What changes will be included?
To see a list of breaking change candidates you can look at the [`breaking_change` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr). New changes might be added between now and when `develop` is closed, and a PR with that label applied is not guaranteed to be merged.
To see a list of breaking changes merge candidates you can look at the [`core` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Acore+is%3Apr). This label is applied whenever a PR is raised or changed, but only if the PR includes changes to core areas of QMK Firmware. A PR with that label applied is not guaranteed to be merged in the current cycle. New changes might be added between now and when `develop` is closed, and it is generally the responsibility of the submitter to handle conflicts. There is also another label used by QMK Collaborators -- `breaking_change_YYYYqN` -- which signifies to maintainers that it is a strong candidate for inclusion, and should be prioritized for review.
If you want your breaking change to be included in this round you need to create a PR with the `breaking_change` label and have it accepted before `develop` closes. After `develop` closes no new breaking changes will be accepted.
If you want your breaking change to be included in this round you need to create a PR and have it accepted by QMK Collaborators before `develop` closes. After `develop` closes, new submissions will be deferred to the next breaking changes cycle.
The simpler your PR is, the easier it is for maintainers to review, thus a higher likelihood of a faster merge. Large PRs tend to require a lot of attention, refactoring, and back-and-forth with subsequent reviews -- with other PRs getting merged in the meantime larger unmerged PRs are far more likely to be susceptible to conflicts.
Criteria for acceptance:
* The PR is complete and ready to merge
* GitHub checks for the PR are green whenever possible
* A "red" check may be disregarded by maintainers if the items flagged are unrelated to the change proposed in the PR
* Modifications to existing files should not need to add license headers to pass lint, for instance.
* If it's not directly related to your PR's functionality, prefer avoiding making a change.
Strongly suggested:
* The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20221126`.
* This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PR's ID.
* This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PRs ID.
* One strong recommendation that the ChangeLog document matches the PR description on GitHub, so as to ensure traceability.
## Checklists
@ -55,7 +60,7 @@ This section documents various processes we use when running the Breaking Change
### 4 Weeks Before Merge
* `develop` is now closed to new PR's, only fixes for current PR's may be merged
* `develop` is now closed to new PRs, only fixes for current PRs may be merged
* Post call for testers: message `@Breaking Changes Updates` on `#qmk_firmware` in Discord:
* `@Breaking Changes Updates -- Hey folks, last day for functional PRs to be raised against qmk_firmware for this breaking changes cycle is today.`
@ -122,12 +127,12 @@ This happens immediately after the previous `develop` branch is merged to `maste
* Validate each submodule SHA1 matches the qmk fork, e.g. for ChibiOS:
* Go to [qmk/ChibiOS](https://github.com/qmk/ChibiOS)
* Compare the commit hash in the above output to the commit hash in the repository
* If there's a mismatch, that repository needs to have its `master` branch updated to match (otherwise Configurator won't work):
* If there's a mismatch, that repository needs to have its `qmk-master` branch updated to match (otherwise Configurator won't work):
* `cd lib/chibios`
* `git fetch --all`
* `git checkout master`
* `git checkout qmk-master`
* `git reset --hard <commit hash>`
* `git push origin master --force-with-lease`
* `git push origin qmk-master --force-with-lease`
* Announce that both `master` and `develop` are now unlocked -- message `@Breaking Changes Updates` on `#qmk_firmware` in Discord:
* `@Breaking Changes Updates -- Hey folks, develop has now been merged into master -- newest batch of changes are now available for everyone to use!`

View file

@ -2,6 +2,8 @@
This page links to all previous changelogs from the QMK Breaking Changes process.
* [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0
* [2022 Nov 26](ChangeLog/20221126.md) - version 0.19.0
* [2022 Aug 27](ChangeLog/20220827.md) - version 0.18.0
* [2022 May 28](ChangeLog/20220528.md) - version 0.17.0
* [2022 Feb 26](ChangeLog/20220226.md) - version 0.16.0

View file

@ -4,7 +4,7 @@ ChibiOS and ChibiOS-Contrib need to be updated in tandem -- the latter has a bra
## Getting ChibiOS
* `svn` Initialisation:
* `svn` Initialization:
* Only needed to be done once
* You might need to separately install `git-svn` package in your OS's package manager
* `git svn init --stdlayout --prefix='svn/' http://svn.osdn.net/svnroot/chibios/`
@ -21,7 +21,7 @@ ChibiOS and ChibiOS-Contrib need to be updated in tandem -- the latter has a bra
## Getting ChibiOS-Contrib
* `git` Initialisation:
* `git` Initialization:
* `git clone git@github.com:qmk/ChibiOS-Contrib`
* `git remote add upstream https://github.com/ChibiOS/ChibiOS-Contrib`
* `git checkout -b chibios-20.3.x upstream/chibios-20.3.x`
@ -51,9 +51,22 @@ ChibiOS and ChibiOS-Contrib need to be updated in tandem -- the latter has a bra
* `./util/chibios_conf_updater.sh`
* Build everything
* `cd $QMK_FIRMWARE`
* `qmk multibuild -j4`
* `qmk mass-compile -j 4`
* Make sure there are no errors
* Push to the repo
* `git commit -am 'Update ChibiOS to 99.9.9'`
* `git push --set-upstream origin chibios-version-bump`
* Make a PR to qmk_firmware with the new branch
## When merging a PR containing an upgrade of ChibiOS/ChibiOS-Contrib:
* Update the target branch if the merge target was `master`:
* `git checkout qmk-master`
* `git reset --hard develop_YYYY_qN`
* `git push origin qmk-master --force-with-lease`
* Update the target branch if the merge target was `develop`:
* `git checkout qmk-develop`
* `git reset --hard develop_YYYY_qN`
* `git push origin qmk-develop --force-with-lease`
Note that when merging `develop` to `master`, the first workflow should still be followed.

View file

@ -223,7 +223,7 @@ Check your environment and report problems only:
## `qmk format-json`
Formats a JSON file in a (mostly) human-friendly way. Will usually correctly detect the format of the JSON (info.json or keymap.json) but you can override this with `--format` if neccesary.
Formats a JSON file in a (mostly) human-friendly way. Will usually correctly detect the format of the JSON (info.json or keymap.json) but you can override this with `--format` if necessary.
**Usage**:

View file

@ -162,7 +162,7 @@ del(cli.config.<section>.<key>)
## Writing The Configuration File
The configuration is not written out when it is changed. Most commands do not need to do this. We prefer to have the user change their configuration deliberitely using `qmk config`.
The configuration is not written out when it is changed. Most commands do not need to do this. We prefer to have the user change their configuration deliberately using `qmk config`.
You can use `cli.save_config()` to write out the configuration.

View file

@ -24,7 +24,7 @@ Most of our style is pretty easy to pick up on, but right now it's not entirely
* Readability is more important than consistency.
* Follow the file's existing style. If the file is mixed, follow the style that makes sense for the section you are modifying.
* When indenting, keep the hash at the start of the line and add whitespace between `#` and `if`, starting with 4 spaces after the `#`.
* You can follow the indention level of the surrounding C code, or preprocessor directives can have their own indentation levels. Choose the style that best communicates the intent of your code.
* You can follow the indentation level of the surrounding C code, or preprocessor directives can have their own indentation levels. Choose the style that best communicates the intent of your code.
Here is an example for easy reference:

View file

@ -2,7 +2,7 @@
Most of our style follows PEP8 with some local modifications to make things less nit-picky.
* We target Python 3.7 for compatability with all supported platforms.
* We target Python 3.7 for compatibility with all supported platforms.
* We indent using four (4) spaces (soft tabs)
* We encourage liberal use of comments
* Think of them as a story describing the feature
@ -21,7 +21,7 @@ You can use [yapf](https://github.com/google/yapf) to style your code. We provid
We don't have a hard and fast rule for when to use `import ...` vs `from ... import ...`. Understandability and maintainability is our ultimate goal.
Generally we prefer to import specific function and class names from a module to keep code shorter and easier to understand. Sometimes this results in a name that is ambiguous, and in such cases we prefer to import the module instead. You should avoid using the "as" keyword when importing, unless you are importing a compatability module.
Generally we prefer to import specific function and class names from a module to keep code shorter and easier to understand. Sometimes this results in a name that is ambiguous, and in such cases we prefer to import the module instead. You should avoid using the "as" keyword when importing, unless you are importing a compatibility module.
Imports should be one line per module. We group import statements together using the standard python rules- system, 3rd party, local.

View file

@ -2,7 +2,17 @@
QMK is nearly infinitely configurable. Wherever possible we err on the side of allowing users to customize their keyboard, even at the expense of code size. That level of flexibility makes for a daunting configuration experience, however.
There are two main types of configuration files in QMK- `config.h` and `rules.mk`. These files exist at various levels in QMK and all files of the same type are combined to build the final configuration. The levels, from lowest priority to highest priority, are:
There are three main types of configuration files in QMK:
* `config.h`, which contains various preprocessor directives (`#define`, `#ifdef`)
* `rules.mk`, which contains additional variables
* `info.json`, which is utilized for [data-driven configuration](https://docs.qmk.fm/#/data_driven_config)
This page will only discuss the first two types, `config.h` and `rules.mk`.
?> While not all settings have data-driven equivalents yet, keyboard makers are encouraged to utilize the `info.json` file to set the metadata for their boards when possible. See the [`info.json` Format](https://docs.qmk.fm/#/reference_info_json) page for more details.
These files exist at various levels in QMK and all files of the same type are combined to build the final configuration. The levels, from lowest priority to highest priority, are:
* QMK Default
* Keyboard
@ -27,23 +37,18 @@ This level contains all of the options for that particular keymap. If you wish t
# The `config.h` File
This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files, or anything besides this:
```c
#include "config_common.h"
```
This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files.
## Hardware Options
* `#define VENDOR_ID 0x1234`
* defines your VID, and for most DIY projects, can be whatever you want
* `#define PRODUCT_ID 0x5678`
* defines your PID, and for most DIY projects, can be whatever you want
* `#define DEVICE_VER 0`
* `#define DEVICE_VER 0x0100`
* defines the device version (often used for revisions)
* `#define MANUFACTURER Me`
* `#define MANUFACTURER "Me"`
* generally who/whatever brand produced the board
* `#define PRODUCT Board`
* `#define PRODUCT "Board"`
* the name of the keyboard
* `#define MATRIX_ROWS 5`
* the number of rows in your keyboard's matrix
@ -159,14 +164,18 @@ If you define these options you will enable the associated feature, which may in
* `#define IGNORE_MOD_TAP_INTERRUPT`
* makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys.
* See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for details
* `#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
* enables handling for per key `IGNORE_MOD_TAP_INTERRUPT` settings
* `#define TAPPING_FORCE_HOLD`
* makes it possible to use a dual role key as modifier shortly after having been tapped
* See [Tapping Force Hold](tap_hold.md#tapping-force-hold)
* Breaks any Tap Toggle functionality (`TT` or the One Shot Tap Toggle)
* `#define TAPPING_FORCE_HOLD_PER_KEY`
* enables handling for per key `TAPPING_FORCE_HOLD` settings
* `#define QUICK_TAP_TERM 100`
* tap-then-hold timing to use a dual role key to repeat keycode
* See [Quick Tap Term](tap_hold.md#quick-tap-term)
* Changes the timing of Tap Toggle functionality (`TT` or the One Shot Tap Toggle)
* Defaults to `TAPPING_TERM` if not defined
* `#define QUICK_TAP_TERM_PER_KEY`
* enables handling for per key `QUICK_TAP_TERM` settings
* `#define HOLD_ON_OTHER_KEY_PRESS`
* selects the hold action of a dual-role key as soon as the tap of the dual-role key is interrupted by the press of another key.
* See "[hold on other key press](tap_hold.md#hold-on-other-key-press)" for details
* `#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY`
* enables handling for per key `HOLD_ON_OTHER_KEY_PRESS` settings
* `#define LEADER_TIMEOUT 300`
* how long before the leader key times out
* If you're having issues finishing the sequence before it times out, you may need to increase the timeout setting. Or you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped.
@ -185,7 +194,7 @@ If you define these options you will enable the associated feature, which may in
* `#define COMBO_TERM 200`
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
* `#define COMBO_MUST_HOLD_MODS`
* Flag for enabling extending timeout on Combos containing modifers
* Flag for enabling extending timeout on Combos containing modifiers
* `#define COMBO_MOD_TERM 200`
* Allows for extending COMBO_TERM for mod keys while mid-combo.
* `#define COMBO_MUST_HOLD_PER_COMBO`
@ -197,11 +206,14 @@ If you define these options you will enable the associated feature, which may in
* `#define COMBO_NO_TIMER`
* Disable the combo timer completely for relaxed combos.
* `#define TAP_CODE_DELAY 100`
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds.
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds and defaults to `0`.
* `#define TAP_HOLD_CAPS_DELAY 80`
* Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPS_LOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 80 ms if not defined. For macOS, you may want to set this to 200 or higher.
* `#define KEY_OVERRIDE_REPEAT_DELAY 500`
* Sets the key repeat interval for [key overrides](feature_key_overrides.md).
* `#define LEGACY_MAGIC_HANDLING`
* Enables magic configuration handling for advanced keycodes (such as Mod Tap and Layer Tap)
## RGB Light Configuration
@ -316,6 +328,13 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_USB_TIMEOUT_POLL 10`
* Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
* `#define SPLIT_WATCHDOG_ENABLE`
* Reboot slave if no communication from master within timeout.
* Helps resolve issue where both sides detect as slave using `SPLIT_USB_DETECT`
* `#define SPLIT_WATCHDOG_TIMEOUT 3000`
* Maximum slave timeout when waiting for communication from master when using `SPLIT_WATCHDOG_ENABLE`
* `#define FORCED_SYNC_THROTTLE_MS 100`
* Deadline for synchronizing data from master to slave when using the QMK-provided split transport.

View file

@ -54,9 +54,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[1] = LAYOUT_all(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DEC, BL_INC,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DOWN, BL_UP,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_MNXT, KC_VOLD,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_MNXT, KC_VOLD,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
@ -82,9 +82,9 @@ The default keymap uses the `LAYOUT_all` macro, so that will be the value of the
"KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "MO(1)", "KC_RGUI", "KC_RCTL", "KC_LEFT", "KC_DOWN", "KC_RGHT"
],
[
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DEC", "BL_INC",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DOWN", "BL_UP",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_VOLU",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RESET", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY", "KC_MNXT", "KC_VOLD",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "QK_BOOT", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY", "KC_MNXT", "KC_VOLD",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS"
@ -122,26 +122,26 @@ There is a way to support custom keycodes: if the logic for a custom keycode is
```c
enum custom_keycodes {
MACRO_1 = SAFE_RANGE,
MACRO_2,
MACRO_3
CUSTOM_1 = SAFE_RANGE,
CUSTOM_2,
CUSTOM_3
};
...
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case MACRO_1:
case CUSTOM_1:
if (record->event.pressed) {
SEND_STRING("This is macro #1.");
SEND_STRING("This is custom keycode #1.");
}
return false;
case MACRO_2:
case CUSTOM_2:
if (record->event.pressed) {
SEND_STRING("This is macro #2.");
SEND_STRING("This is custom keycode #2.");
}
return false;
case MACRO_3:
case CUSTOM_3:
if (record->event.pressed) {
SEND_STRING("This is macro #3.");
SEND_STRING("This is custom keycode #3.");
}
return false;
}
@ -153,10 +153,9 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
```c
enum keyboard_keycodes {
MACRO_1 = SAFE_RANGE,
MACRO_2,
MACRO_3,
NEW_SAFE_RANGE // Important!
CUSTOM_1 = QK_KB_0,
CUSTOM_2,
CUSTOM_3,
};
```
@ -165,19 +164,19 @@ enum keyboard_keycodes {
```c
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case MACRO_1:
case CUSTOM_1:
if (record->event.pressed) {
SEND_STRING("This is macro #1.");
SEND_STRING("This is custom keycode #1.");
}
return false;
case MACRO_2:
case CUSTOM_2:
if (record->event.pressed) {
SEND_STRING("This is macro #2.");
SEND_STRING("This is custom keycode #2.");
}
return false;
case MACRO_3:
case CUSTOM_3:
if (record->event.pressed) {
SEND_STRING("This is macro #3.");
SEND_STRING("This is custom keycode #3.");
}
return false;
}
@ -185,8 +184,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
};
```
Note the call to `process_record_user()` at the end. Additionally, users of the keyboard will need to use `NEW_SAFE_RANGE` instead of `SAFE_RANGE` if they wish to add their own custom keycodes at keymap level, beyond what is provided by the keyboard.
Note the call to `process_record_user()` at the end.
## Additional Reading :id=additional-reading

View file

@ -118,8 +118,8 @@ and navigating to `http://localhost:8936/`.
Most first-time QMK contributors start with their personal keymaps. We try to keep keymap standards pretty casual (keymaps, after all, reflect the personality of their creators) but we do ask that you follow these guidelines to make it easier for others to discover and learn from your keymap.
* Write a `readme.md` using [the template](documentation_templates.md).
* All Keymap PR's are squashed, so if you care about how your commits are squashed you should do it yourself
* Do not lump features in with keymap PR's. Submit the feature first and then a second PR for the keymap.
* All Keymap PRs are squashed, so if you care about how your commits are squashed you should do it yourself
* Do not lump features in with keymap PRs. Submit the feature first and then a second PR for the keymap.
* Do not include `Makefile`s in your keymap folder (they're no longer used)
* Update copyrights in file headers (look for `%YOUR_NAME%`)
@ -143,7 +143,7 @@ Before you put a lot of work into building your new feature you should make sure
* [Chat on Discord](https://discord.gg/Uq7gcHh)
* [Open an Issue](https://github.com/qmk/qmk_firmware/issues/new)
Feature and Bug Fix PR's affect all keyboards. We are also in the process of restructuring QMK. For this reason it is especially important for significant changes to be discussed before implementation has happened. If you open a PR without talking to us first please be prepared to do some significant rework if your choices do not mesh well with our planned direction.
Feature and Bug Fix PRs affect all keyboards. We are also in the process of restructuring QMK. For this reason it is especially important for significant changes to be discussed before implementation has happened. If you open a PR without talking to us first please be prepared to do some significant rework if your choices do not mesh well with our planned direction.
Here are some things to keep in mind when working on your feature or bug fix.

View file

@ -77,7 +77,7 @@ void matrix_init(void) {
debounce_init(MATRIX_ROWS);
// This *must* be called for correct keyboard behavior
matrix_init_quantum();
matrix_init_kb();
}
uint8_t matrix_scan(void) {
@ -89,7 +89,7 @@ uint8_t matrix_scan(void) {
changed = debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
// This *must* be called for correct keyboard behavior
matrix_scan_quantum();
matrix_scan_kb();
return changed;
}

View file

@ -102,11 +102,11 @@ These are the three main initialization functions, listed in the order that they
## Keyboard Pre Initialization code
This runs very early during startup, even before the USB has been started.
This runs very early during startup, even before the USB has been started.
Shortly after this, the matrix is initialized.
For most users, this shouldn't be used, as it's primarily for hardware oriented initialization.
For most users, this shouldn't be used, as it's primarily for hardware oriented initialization.
However, if you have hardware stuff that you need initialized, this is the best place for it (such as initializing LED pins).
@ -134,9 +134,9 @@ void keyboard_pre_init_user(void) {
## Matrix Initialization Code
This is called when the matrix is initialized, and after some of the hardware has been set up, but before many of the features have been initialized.
This is called when the matrix is initialized, and after some of the hardware has been set up, but before many of the features have been initialized.
This is useful for setting up stuff that you may need elsewhere, but isn't hardware related nor is dependant on where it's started.
This is useful for setting up stuff that you may need elsewhere, but isn't hardware related nor is dependant on where it's started.
### `matrix_init_*` Function Documentation
@ -227,185 +227,6 @@ void suspend_wakeup_init_user(void) {
* Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
* Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
# Layer Change Code :id=layer-change-code
This runs code every time that the layers get changed. This can be useful for layer indication, or custom layer handling.
### Example `layer_state_set_*` Implementation
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example.
```c
layer_state_t layer_state_set_user(layer_state_t state) {
switch (get_highest_layer(state)) {
case _RAISE:
rgblight_setrgb (0x00, 0x00, 0xFF);
break;
case _LOWER:
rgblight_setrgb (0xFF, 0x00, 0x00);
break;
case _PLOVER:
rgblight_setrgb (0x00, 0xFF, 0x00);
break;
case _ADJUST:
rgblight_setrgb (0x7A, 0x00, 0xFF);
break;
default: // for any other layers, or the default layer
rgblight_setrgb (0x00, 0xFF, 0xFF);
break;
}
return state;
}
```
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
### `layer_state_set_*` Function Documentation
* Keyboard/Revision: `layer_state_t layer_state_set_kb(layer_state_t state)`
* Keymap: `layer_state_t layer_state_set_user(layer_state_t state)`
The `state` is the bitmask of the active layers, as explained in the [Keymap Overview](keymap.md#keymap-layer-status)
# Persistent Configuration (EEPROM)
This allows you to configure persistent settings for your keyboard. These settings are stored in the EEPROM of your controller, and are retained even after power loss. The settings can be read with `eeconfig_read_kb` and `eeconfig_read_user`, and can be written to using `eeconfig_update_kb` and `eeconfig_update_user`. This is useful for features that you want to be able to toggle (like toggling rgb layer indication). Additionally, you can use `eeconfig_init_kb` and `eeconfig_init_user` to set the default values for the EEPROM.
The complicated part here, is that there are a bunch of ways that you can store and access data via EEPROM, and there is no "correct" way to do this. However, you only have a DWORD (4 bytes) for each function.
Keep in mind that EEPROM has a limited number of writes. While this is very high, it's not the only thing writing to the EEPROM, and if you write too often, you can potentially drastically shorten the life of your MCU.
* If you don't understand the example, then you may want to avoid using this feature, as it is rather complicated.
### Example Implementation
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here. This is a complex function, and has a lot going on. In fact, it uses a lot of the above functions to work!
In your keymap.c file, add this to the top:
```c
typedef union {
uint32_t raw;
struct {
bool rgb_layer_change :1;
};
} user_config_t;
user_config_t user_config;
```
This sets up a 32 bit structure that we can store settings with in memory, and write to the EEPROM. Using this removes the need to define variables, since they're defined in this structure. Remember that `bool` (boolean) values use 1 bit, `uint8_t` uses 8 bits, `uint16_t` uses up 16 bits. You can mix and match, but changing the order can cause issues, as it will change the values that are read and written.
We're using `rgb_layer_change`, for the `layer_state_set_*` function, and use `keyboard_post_init_user` and `process_record_user` to configure everything.
Now, using the `keyboard_post_init_user` code above, you want to add `eeconfig_read_user()` to it, to populate the structure you've just created. And you can then immediately use this structure to control functionality in your keymap. And It should look like:
```c
void keyboard_post_init_user(void) {
// Call the keymap level matrix init.
// Read the user config from EEPROM
user_config.raw = eeconfig_read_user();
// Set default layer, if enabled
if (user_config.rgb_layer_change) {
rgblight_enable_noeeprom();
rgblight_sethsv_noeeprom_cyan();
rgblight_mode_noeeprom(1);
}
}
```
The above function will use the EEPROM config immediately after reading it, to set the default layer's RGB color. The "raw" value of it is converted in a usable structure based on the "union" that you created above.
```c
layer_state_t layer_state_set_user(layer_state_t state) {
switch (get_highest_layer(state)) {
case _RAISE:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
break;
case _LOWER:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
break;
case _PLOVER:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_green(); rgblight_mode_noeeprom(1); }
break;
case _ADJUST:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_white(); rgblight_mode_noeeprom(1); }
break;
default: // for any other layers, or the default layer
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_cyan(); rgblight_mode_noeeprom(1); }
break;
}
return state;
}
```
This will cause the RGB underglow to be changed ONLY if the value was enabled. Now to configure this value, create a new keycode for `process_record_user` called `RGB_LYR`. Additionally, we want to make sure that if you use the normal RGB codes, that it turns off Using the example above, make it look this:
```c
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case FOO:
if (record->event.pressed) {
// Do something when pressed
} else {
// Do something else when release
}
return false; // Skip all further processing of this key
case KC_ENTER:
// Play a tone when enter is pressed
if (record->event.pressed) {
PLAY_SONG(tone_qwerty);
}
return true; // Let QMK send the enter press/release events
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
if (record->event.pressed) {
user_config.rgb_layer_change ^= 1; // Toggles the status
eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
if (user_config.rgb_layer_change) { // if layer state indication is enabled,
layer_state_set(layer_state); // then immediately update the layer color
}
}
return false;
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
if (user_config.rgb_layer_change) { // only if this is enabled
user_config.rgb_layer_change = false; // disable it, and
eeconfig_update_user(user_config.raw); // write the setings to EEPROM
}
}
return true; break;
default:
return true; // Process all other keycodes normally
}
}
```
And lastly, you want to add the `eeconfig_init_user` function, so that when the EEPROM is reset, you can specify default values, and even custom actions. To force an EEPROM reset, use the `EEP_RST` keycode or [Bootmagic Lite](feature_bootmagic.md) functionallity. For example, if you want to set rgb layer indication by default, and save the default valued.
```c
void eeconfig_init_user(void) { // EEPROM is getting reset!
user_config.raw = 0;
user_config.rgb_layer_change = true; // We want this enabled by default
eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
// use the non noeeprom versions, to write these values to EEPROM too
rgblight_enable(); // Enable RGB by default
rgblight_sethsv_cyan(); // Set it to CYAN by default
rgblight_mode(1); // set to solid by default
}
```
And you're done. The RGB layer indication will only work if you want it to. And it will be saved, even after unplugging the board. And if you use any of the RGB codes, it will disable the layer indication, so that it stays on the mode and color that you set it to.
### 'EECONFIG' Function Documentation
* Keyboard/Revision: `void eeconfig_init_kb(void)`, `uint32_t eeconfig_read_kb(void)` and `void eeconfig_update_kb(uint32_t val)`
* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.
# Deferred Execution :id=deferred-execution
QMK has the ability to execute a callback after a specified period of time, rather than having to manually manage timers. To enable this functionality, set `DEFERRED_EXEC_ENABLE = yes` in rules.mk.
@ -471,3 +292,15 @@ If registrations fail, then you can increase this value in your keyboard or keym
```c
#define MAX_DEFERRED_EXECUTORS 16
```
# Advanced topics :id=advanced-topics
This page used to encompass a large set of features. We have moved many sections that used to be part of this page to their own pages. Everything below this point is simply a redirect so that people following old links on the web find what they're looking for.
## Layer Change Code :id=layer-change-code
[Layer change code](feature_layers.md#layer-change-code)
## Persistent Configuration (EEPROM) :id=persistent-configuration-eeprom
[Persistent Configuration (EEPROM)](feature_eeprom.md)

View file

@ -41,7 +41,7 @@ In other cases you should group like options together in an `object`. This is pa
### Add a mapping
In most cases you can add a simple mapping. These are maintained as JSON files in `data/mappings/info_config.json` and `data/mappings/info_rules.json`, and control mapping for `config.h` and `rules.mk`, respectively. Each mapping is keyed by the `config.h` or `rules.mk` variable, and the value is a hash with the following keys:
In most cases you can add a simple mapping. These are maintained as JSON files in `data/mappings/info_config.hjson` and `data/mappings/info_rules.hjson`, and control mapping for `config.h` and `rules.mk`, respectively. Each mapping is keyed by the `config.h` or `rules.mk` variable, and the value is a hash with the following keys:
* `info_key`: (required) The location within `info.json` for this value. See below.
* `value_type`: (optional) Default `raw`. The format for this variable's value. See below.

View file

@ -4,7 +4,7 @@ This page documents the templates you should use when submitting new Keymaps and
## Keymap `readme.md` Template :id=keyboard-readmemd-template
Most keymaps have an image depicting the layout. You can use [Keyboard Layout Editor](https://keyboard-layout-editor.com) to create an image. Upload it to [Imgur](https://imgur.com) or another hosting service, please do not include images in your Pull Request.
Most keymaps have an image depicting the layout. You can use [Keyboard Layout Editor](http://keyboard-layout-editor.com) to create an image. Upload it to [Imgur](https://imgur.com) or another hosting service, please do not include images in your Pull Request.
Below the image you should write a short description to help people understand your keymap.
@ -36,5 +36,17 @@ Make example for this keyboard (after setting up your build environment):
make planck/rev4:default
Flashing example for this keyboard:
make planck/rev4:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
```

View file

@ -8,7 +8,7 @@ We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have
## Installation
Put your keyboard into bootloader mode, either by hitting the `RESET` keycode (which may be on a different layer), or by pressing the reset switch that's usually located on the underside of the board. If your keyboard has neither, try holding Escape or Space+`B` as you plug it in (see the [Bootmagic Lite](feature_bootmagic.md) docs for more details). Some boards use [Command](feature_command.md) instead of Bootmagic; in this case, you can enter bootloader mode by hitting Left Shift+Right Shift+`B` or Left Shift+Right Shift+Escape at any point while the keyboard is plugged in.
Put your keyboard into bootloader mode, either by hitting the `QK_BOOT` keycode (which may be on a different layer), or by pressing the reset switch that's usually located on the underside of the board. If your keyboard has neither, try holding Escape or Space+`B` as you plug it in (see the [Bootmagic Lite](feature_bootmagic.md) docs for more details). Some boards use [Command](feature_command.md) instead of Bootmagic; in this case, you can enter bootloader mode by hitting Left Shift+Right Shift+`B` or Left Shift+Right Shift+Escape at any point while the keyboard is plugged in.
Some keyboards may have specific instructions for entering the bootloader. For example, the [Bootmagic Lite](feature_bootmagic.md) key (default: Escape) might be on a different key, e.g. Left Control; or the magic combination for Command (default: Left Shift+Right Shift) might require you to hold something else, e.g. Left Control+Right Control. Refer to the board's README file if you are unsure.
To put a device in bootloader mode with USBaspLoader, tap the `RESET` button while holding down the `BOOT` button.

View file

@ -4,7 +4,7 @@ This page details various common questions people have about troubleshooting the
## Debugging :id=debugging
Your keyboard will output debug information if you have `CONSOLE_ENABLE = yes` in your `rules.mk`. By default the output is very limited, but you can turn on debug mode to increase the amount of debug output. Use the `DEBUG` keycode in your keymap, use the [Command](feature_command.md) feature to enable debug mode, or add the following code to your keymap.
Your keyboard will output debug information if you have `CONSOLE_ENABLE = yes` in your `rules.mk`. By default the output is very limited, but you can turn on debug mode to increase the amount of debug output. Use the `DB_TOGG` keycode in your keymap, use the [Command](feature_command.md) feature to enable debug mode, or add the following code to your keymap.
```c
void keyboard_post_init_user(void) {
@ -133,3 +133,4 @@ Check:
- Set `debug_enable=true`. See [Debugging](#debugging)
- Try using `print` function instead of debug print. See **common/print.h**.
- Disconnect other devices with console function. See [Issue #97](https://github.com/tmk/tmk_keyboard/issues/97).
- Ensure all strings end with a newline character (`\n`). QMK Toolbox prints console output on a per-line basis.

View file

@ -10,7 +10,7 @@ You probably don't want to "brick" your keyboard, making it impossible
to rewrite firmware onto it. Here are some of the parameters to show
what things are (and likely aren't) too risky.
- If your keyboard map does not include RESET, then, to get into DFU
- If your keyboard map does not include QK_BOOT, then, to get into DFU
mode, you will need to press the reset button on the PCB, which
requires unscrewing the bottom.
- Messing with tmk_core / common files might make the keyboard

View file

@ -161,7 +161,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
```
# Legacy Content :id=legacy-content
# Advanced topics :id=advanced-topics
This page used to encompass a large set of features. We have moved many sections that used to be part of this page to their own pages. Everything below this point is simply a redirect so that people following old links on the web find what they're looking for.

View file

@ -114,7 +114,7 @@ The audio core offers interface functions to get/set/change the tone multiplexin
There's a couple of different sounds that will automatically be enabled without any other configuration:
```
STARTUP_SONG // plays when the keyboard starts up (audio.c)
GOODBYE_SONG // plays when you press the RESET key (quantum.c)
GOODBYE_SONG // plays when you press the QK_BOOT key (quantum.c)
AG_NORM_SONG // plays when you press AG_NORM (quantum.c)
AG_SWAP_SONG // plays when you press AG_SWAP (quantum.c)
CG_NORM_SONG // plays when you press CG_NORM (quantum.c)
@ -161,9 +161,11 @@ It's advised that you wrap all audio features in `#ifdef AUDIO_ENABLE` / `#endif
The available keycodes for audio are:
* `AU_ON` - Turn Audio Feature on
* `AU_OFF` - Turn Audio Feature off
* `AU_TOG` - Toggle Audio Feature state
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_AUDIO_ON` |`AU_ON` |Turns on Audio Feature |
|`QK_AUDIO_OFF` |`AU_OFF` |Turns off Audio Feature |
|`QK_AUDIO_TOGGLE` |`AU_TOGG`|Toggles Audio state |
!> These keycodes turn all of the audio functionality on and off. Turning it off means that audio feedback, audio clicky, music mode, etc. are disabled, completely.
@ -177,7 +179,7 @@ The available keycodes for audio are:
|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. |
|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. |
|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) |
|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the RESET key (quantum.c) |
|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) |
|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) |
|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) |
|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) |
@ -219,6 +221,12 @@ Aka "audio effects", different ones can be enabled by setting in `config.h` thes
`#define AUDIO_VOICES` to enable the feature, and `#define AUDIO_VOICE_DEFAULT something` to select a specific effect
for details see quantum/audio/voices.h and .c
Keycodes available:
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_AUDIO_VOICE_NEXT` |`AU_NEXT`|Cycles through the audio voices |
|`QK_AUDIO_VOICE_PREVIOUS`|`AU_PREV`|Cycles through the audio voices in reverse |
## Music Mode
@ -228,10 +236,14 @@ Recording is experimental due to some memory issues - if you experience some wei
Keycodes available:
* `MU_ON` - Turn music mode on
* `MU_OFF` - Turn music mode off
* `MU_TOG` - Toggle music mode
* `MU_MOD` - Cycle through the music modes:
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_MUSIC_ON` |`MU_ON` |Turns on Music Mode |
|`QK_MUSIC_OFF` |`MU_OFF` |Turns off Music Mode |
|`QK_MUSIC_TOGGLE` |`MU_TOGG`|Toggles Music Mode |
|`QK_MUSIC_MODE_NEXT` |`MU_NEXT`|Cycles through the music modes |
Available Modes:
* `CHROMATIC_MODE` - Chromatic scale, row changes the octave
* `GUITAR_MODE` - Chromatic scale, but the row changes the string (+5 st)
* `VIOLIN_MODE` - Chromatic scale, but the row changes the string (+7 st)
@ -300,13 +312,16 @@ You can look at the [Planck Keyboard](https://github.com/qmk/qmk_firmware/blob/e
This adds a click sound each time you hit a button, to simulate click sounds from the keyboard. And the sounds are slightly different for each keypress, so it doesn't sound like a single long note, if you type rapidly.
* `CK_TOGG` - Toggles the status (will play sound if enabled)
* `CK_ON` - Turns on Audio Click (plays sound)
* `CK_OFF` - Turns off Audio Click (doesn't play sound)
* `CK_RST` - Resets the frequency to the default state (plays sound at default frequency)
* `CK_UP` - Increases the frequency of the clicks (plays sound at new frequency)
* `CK_DOWN` - Decreases the frequency of the clicks (plays sound at new frequency)
Keycodes available:
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_AUDIO_CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|`QK_AUDIO_CLICKY_ON` |`CK_ON` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_OFF` |`CK_OFF` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|`QK_AUDIO_CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|`QK_AUDIO_CLICKY_RESET` |`CK_RST` |Resets frequency to default |
The feature is disabled by default, to save space. To enable it, add this to your `config.h`:
@ -333,16 +348,20 @@ See [MIDI](feature_midi.md)
## Audio Keycodes
|Key |Aliases |Description |
|----------------|---------|----------------------------------|
|`AU_ON` | |Audio mode on |
|`AU_OFF` | |Audio mode off |
|`AU_TOG` | |Toggles Audio mode |
|`CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|`CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|`CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|`CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|`MU_ON` | |Turns on Music Mode |
|`MU_OFF` | |Turns off Music Mode |
|`MU_TOG` | |Toggles Music Mode |
|`MU_MOD` | |Cycles through the music modes |
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_AUDIO_ON` |`AU_ON` |Turns on Audio Feature |
|`QK_AUDIO_OFF` |`AU_OFF` |Turns off Audio Feature |
|`QK_AUDIO_TOGGLE` |`AU_TOGG`|Toggles Audio state |
|`QK_AUDIO_CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|`QK_AUDIO_CLICKY_ON` |`CK_ON` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_OFF` |`CK_OFF` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|`QK_AUDIO_CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|`QK_AUDIO_CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|`QK_MUSIC_ON` |`MU_ON` |Turns on Music Mode |
|`QK_MUSIC_OFF` |`MU_OFF` |Turns off Music Mode |
|`QK_MUSIC_TOGGLE` |`MU_TOGG`|Toggles Music Mode |
|`QK_MUSIC_MODE_NEXT` |`MU_NEXT`|Cycles through the music modes |
|`QK_AUDIO_VOICE_NEXT` |`AU_NEXT`|Cycles through the audio voices |
|`QK_AUDIO_VOICE_PREVIOUS`|`AU_PREV`|Cycles through the audio voices in reverse |

View file

@ -281,16 +281,7 @@ Tap Hold Configurations work a little differently when using Retro Shift.
Referencing `TAPPING_TERM` makes little sense, as holding longer would result in
shifting one of the keys.
`IGNORE_MOD_TAP_INTERRUPT` changes *only* rolling from a mod tap (releasing it
first), sending both keys instead of the modifier on the second. Its effects on
nested presses are ignored.
As nested taps were changed to act as though `PERMISSIVE_HOLD` is set unless only
`IGNORE_MOD_TAP_INTERRUPT` is (outside of Retro Shift), and Retro Shift ignores
`IGNORE_MOD_TAP_INTERRUPT`, `PERMISSIVE_HOLD` has no effect on Mod Taps.
Nested taps will *always* act as though the `TAPPING_TERM` was exceeded for both
Mod and Layer Tap keys.
`RETRO_SHIFT` enables [`PERMISSIVE_HOLD`-like behaviour](tap_hold.md#permissive-hold) (even if not explicitly enabled) on all mod-taps for which `RETRO_SHIFT` applies.
## Using Auto Shift Setup
@ -300,14 +291,14 @@ This will enable you to define three keys temporarily to increase, decrease and
Map three keys temporarily in your keymap:
| Key Name | Description |
|----------|-----------------------------------------------------|
| KC_ASDN | Lower the Auto Shift timeout variable (down) |
| KC_ASUP | Raise the Auto Shift timeout variable (up) |
| KC_ASRP | Report your current Auto Shift timeout value |
| KC_ASON | Turns on the Auto Shift Function |
| KC_ASOFF | Turns off the Auto Shift Function |
| KC_ASTG | Toggles the state of the Auto Shift feature |
|Keycode |Aliases |Description |
|----------------------|---------|--------------------------------------------|
|`QK_AUTO_SHIFT_DOWN` |`AS_DOWN`|Lower the Auto Shift timeout variable (down)|
|`QK_AUTO_SHIFT_UP` |`AS_UP` |Raise the Auto Shift timeout variable (up) |
|`QK_AUTO_SHIFT_REPORT`|`AS_RPT` |Report your current Auto Shift timeout value|
|`QK_AUTO_SHIFT_ON` |`AS_ON` |Turns on the Auto Shift Function |
|`QK_AUTO_SHIFT_OFF` |`AS_OFF` |Turns off the Auto Shift Function |
|`QK_AUTO_SHIFT_TOGGLE`|`AS_TOGG`|Toggles the state of the Auto Shift feature |
Compile and upload your new firmware.
@ -318,18 +309,18 @@ completely normal and with no intention of shifted keys.
1. Type multiple sentences of alphabetical letters.
2. Observe any upper case letters.
3. If there are none, press the key you have mapped to `KC_ASDN` to decrease
3. If there are none, press the key you have mapped to `AS_DOWN` to decrease
time Auto Shift timeout value and go back to step 1.
4. If there are some upper case letters, decide if you need to work on tapping
those keys with less down time, or if you need to increase the timeout.
5. If you decide to increase the timeout, press the key you have mapped to
`KC_ASUP` and go back to step 1.
`AS_UP` and go back to step 1.
6. Once you are happy with your results, press the key you have mapped to
`KC_ASRP`. The keyboard will type by itself the value of your
`AS_RPT`. The keyboard will type by itself the value of your
`AUTO_SHIFT_TIMEOUT`.
7. Update `AUTO_SHIFT_TIMEOUT` in your `config.h` with the value reported.
8. Add `AUTO_SHIFT_NO_SETUP` to your `config.h`.
9. Remove the key bindings `KC_ASDN`, `KC_ASUP` and `KC_ASRP`.
9. Remove the key bindings `AS_DOWN`, `AS_UP` and `AS_RPT`.
10. Compile and upload your new firmware.
#### An Example Run
@ -337,17 +328,17 @@ completely normal and with no intention of shifted keys.
hello world. my name is john doe. i am a computer programmer playing with
keyboards right now.
[PRESS KC_ASDN quite a few times]
[PRESS AS_DOWN quite a few times]
heLLo woRLd. mY nAMe is JOHn dOE. i AM A compUTeR proGRaMMER PlAYiNG witH
KEYboArDS RiGHT NOw.
[PRESS KC_ASUP a few times]
[PRESS AS_UP a few times]
hello world. my name is john Doe. i am a computer programmer playing with
keyboarDs right now.
[PRESS KC_ASRP]
[PRESS AS_RPT]
115

295
docs/feature_autocorrect.md Normal file
View file

@ -0,0 +1,295 @@
# Autocorrect
There are a lot of words that are prone to being typed incorrectly, due to habit, sequence or just user error. This feature leverages your firmware to automatically correct these errors, to help reduce typos.
## How does it work? :id=how-does-it-work
The feature maintains a small buffer of recent key presses. On each key press, it checks whether the buffer ends in a recognized typo, and if so, automatically sends keystrokes to correct it.
The tricky part is how to efficiently check the buffer for typos. We dont want to spend too much memory or time on storing or searching the typos. A good solution is to represent the typos with a trie data structure. A trie is a tree data structure where each node is a letter, and words are formed by following a path to one of the leaves.
![An example trie](https://i.imgur.com/HL5DP8H.png)
Since we search whether the buffer ends in a typo, we store the trie writing in reverse. The trie is queried starting from the last letter, then second to last letter, and so on, until either a letter doesnt match or we reach a leaf, meaning a typo was found.
## How do I enable Autocorrection :id=how-do-i-enable-autocorrection
In your `rules.mk`, add this:
```make
AUTOCORRECT_ENABLE = yes
```
Additionally, you will need a library for autocorrection. A small sample library is included by default, so that you can get up and running right away, but you can provide a customized library.
By default, autocorrect is disabled. To enable it, you need to use the `AC_TOGG` keycode to enable it. The status is stored in persistent memory, so you shouldn't need to enabled it again.
## Customizing autocorrect library :id=customizing-autocorrect-library
To provide a custom library, you need to create a text file with the corrections. For instance:
```text
:thier -> their
fitler -> filter
lenght -> length
ouput -> output
widht -> width
```
The syntax is `typo -> correction`. Typos and corrections are case insensitive, and any whitespace before or after the typo and correction is ignored. The typo must be only the letters az, or the special character : representing a word break. The correction may have any non-unicode characters.
Then, run:
```sh
qmk generate-autocorrect-data autocorrect_dictionary.txt
```
This will process the file and produce an `autocorrect_data.h` file with the trie library, in the folder that you are at. You can specify the keyboard and keymap (eg `-kb planck/rev6 -km jackhumbert`), and it will place the file in that folder instead. But as long as the file is located in your keymap folder, or user folder, it should be picked up automatically.
This file will look like this:
```c
// :thier -> their
// fitler -> filter
// lenght -> length
// ouput -> output
// widht -> width
#define AUTOCORRECT_MIN_LENGTH 5 // "ouput"
#define AUTOCORRECT_MAX_LENGTH 6 // ":thier"
#define DICTIONARY_SIZE 74
static const uint8_t autocorrect_data[DICTIONARY_SIZE] PROGMEM = {85, 7, 0, 23, 35, 0, 0, 8, 0, 76, 16, 0, 15, 25, 0, 0,
11, 23, 44, 0, 130, 101, 105, 114, 0, 23, 12, 9, 0, 131, 108, 116, 101, 114, 0, 75, 42, 0, 24, 64, 0, 0, 71, 49, 0,
10, 56, 0, 0, 12, 26, 0, 129, 116, 104, 0, 17, 8, 15, 0, 129, 116, 104, 0, 19, 24, 18, 0, 130, 116, 112, 117, 116,
0};
```
### Avoiding false triggers :id=avoiding-false-triggers
By default, typos are searched within words, to find typos within longer identifiers like maxFitlerOuput. While this is useful, a consequence is that autocorrection will falsely trigger when a typo happens to be a substring of a correctly-spelled word. For instance, if we had thier -> their as an entry, it would falsely trigger on (correct, though relatively uncommon) words like “wealthier” and “filthier.”
The solution is to set a word break : before and/or after the typo to constrain matching. : matches space, period, comma, underscore, digits, and most other non-alpha characters.
|Text |thier |:thier |thier: |:thier: |
|-----------------|:------:|:------:|:------:|:------:|
|see `thier` typo |matches |matches |matches |matches |
|its `thiers` |matches |matches |no |no |
|wealthier words |matches |no |matches |no |
:thier: is most restrictive, matching only when thier is a whole word.
The `qmk generate-autocorrect-data` commands can make an effort to check for entries that would false trigger as substrings of correct words. It searches each typo against a dictionary of 25K English words from the english_words Python package, provided its installed. (run `python3 -m pip install english_words` to install it.)
?> Unfortunately, this is limited to just english words, at this point.
## Overriding Autocorrect
Occasionally you might actually want to type a typo (for instance, while editing autocorrect_dict.txt) without being autocorrected. There are a couple of ways to do this:
1. Begin typing the typo.
2. Before typing the last letter, press and release the Ctrl or Alt key.
3. Type the remaining letters.
This works because the autocorrection implementation doesnt understand hotkeys, so it resets itself whenever a modifier other than shift is held.
Additionally, you can use the `AC_TOGG` keycode to toggle the on/off status for Autocorrect.
### Keycodes :id=keycodes
|Keycode |Aliases |Description |
|-----------------------|---------|----------------------------------------------|
|`QK_AUTOCORRECT_ON` |`AC_ON` |Turns on the Autocorrect feature. |
|`QK_AUTOCORRECT_OFF` |`AC_OFF` |Turns off the Autocorrect feature. |
|`QK_AUTOCORRECT_TOGGLE`|`AC_TOGG`|Toggles the status of the Autocorrect feature.|
## User Callback Functions
### Process Autocorrect
Callback function `bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods)` is available to customise incoming keycodes and handle exceptions. You can use this function to sanitise input before they are passed onto the autocorrect engine
?> Sanitisation of input is required because autocorrect will only match 8-bit [basic keycodes](keycodes_basic.md) for typos. If valid modifier keys or 16-bit keycodes that are part of a user's word input (such as Shift + A) is passed through, they will fail typo letter detection. For example a [Mod-Tap](mod_tap.md) key such as `LCTL_T(KC_A)` is 16-bit and should be masked for the 8-bit `KC_A`.
The default user callback function is found inside `quantum/process_keycode/process_autocorrect.c`. It covers most use-cases for QMK special functions and quantum keycodes, including [overriding autocorrect](#overriding-autocorrect) with a modifier other than shift. The `process_autocorrect_user` function is `weak` defined to allow user's copy inside `keymap.c` (or code files) to overwrite it.
#### Process Autocorrect Example
If you have a custom keycode `QMKBEST` that should be ignored as part of a word, and another custom keycode `QMKLAYER` that should override autocorrect, both can be added to the bottom of the `process_autocorrect_user` `switch` statement in your source code:
```c
bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) {
// See quantum_keycodes.h for reference on these matched ranges.
switch (*keycode) {
// Exclude these keycodes from processing.
case KC_LSFT:
case KC_RSFT:
case KC_CAPS:
case QK_TO ... QK_ONE_SHOT_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX:
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
return false;
// Mask for base keycode from shifted keys.
case QK_LSFT ... QK_LSFT + 255:
case QK_RSFT ... QK_RSFT + 255:
if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) {
*mods |= MOD_LSFT;
} else {
*mods |= MOD_RSFT;
}
*keycode &= 0xFF; // Get the basic keycode.
return true;
#ifndef NO_ACTION_TAPPING
// Exclude tap-hold keys when they are held down
// and mask for base keycode when they are tapped.
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
# ifdef NO_ACTION_LAYER
// Exclude Layer Tap, if layers are disabled
// but action tapping is still enabled.
return false;
# endif
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
// Exclude hold if mods other than Shift is not active
if (!record->tap.count) {
return false;
}
*keycode &= 0xFF;
break;
#else
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
// Exclude if disabled
return false;
#endif
// Exclude swap hands keys when they are held down
// and mask for base keycode when they are tapped.
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
#ifdef SWAP_HANDS_ENABLE
if (*keycode >= 0x56F0 || !record->tap.count) {
return false;
}
*keycode &= 0xFF;
break;
#else
// Exclude if disabled
return false;
#endif
// Handle custom keycodes
case QMKBEST:
return false;
case QMKLAYER:
*typo_buffer_size = 0;
return false;
}
// Disable autocorrect while a mod other than shift is active.
if ((*mods & ~MOD_MASK_SHIFT) != 0) {
*typo_buffer_size = 0;
return false;
}
return true;
}
```
?> In this callback function, `return false` will skip processing of that keycode for autocorrect. Adding `*typo_buffer_size = 0` will also reset the autocorrect buffer at the same time, cancelling any current letters already stored in the buffer.
### 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).
#### Apply Autocorrect Example
This following example will play a sound when a typo is autocorrected and execute the autocorrection itself:
```c
#ifdef AUDIO_ENABLE
float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
#endif
bool apply_autocorrect(uint8_t backspaces, const char *str) {
#ifdef AUDIO_ENABLE
PLAY_SONG(autocorrect_song);
#endif
for (uint8_t i = 0; i < backspaces; ++i) {
tap_code(KC_BSPC);
}
send_string_P(str);
return false;
}
```
?> 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`.
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) {
#ifdef OLED_ENABLE
oled_write_P(PSTR("Auto-corrected"), false);
#endif
return true;
}
```
## Appendix: Trie binary data format :id=appendix
This section details how the trie is serialized to byte data in autocorrect_data. You dont need to care about this to use this autocorrection implementation. But it is documented for the record in case anyone is interested in modifying the implementation, or just curious how it works.
What I did here is fairly arbitrary, but it is simple to decode and gets the job done.
### Encoding :id=encoding
All autocorrection data is stored in a single flat array autocorrect_data. Each trie node is associated with a byte offset into this array, where data for that node is encoded, beginning with root at offset 0. There are three kinds of nodes. The highest two bits of the first byte of the node indicate what kind:
* 00 ⇒ chain node: a trie node with a single child.
* 01 ⇒ branching node: a trie node with multiple children.
* 10 ⇒ leaf node: a leaf, corresponding to a typo and storing its correction.
![An example trie](https://i.imgur.com/HL5DP8H.png)
**Branching node**. Each branch is encoded with one byte for the keycode (KC_AKC_Z) followed by a link to the child node. Links between nodes are 16-bit byte offsets relative to the beginning of the array, serialized in little endian order.
All branches are serialized this way, one after another, and terminated with a zero byte. As described above, the node is identified as a branch by setting the two high bits of the first byte to 01, done by bitwise ORing the first keycode with 64. keycode. The root node for the above figure would be serialized like:
```
+-------+-------+-------+-------+-------+-------+-------+
| R|64 | node 2 | T | node 3 | 0 |
+-------+-------+-------+-------+-------+-------+-------+
```
**Chain node**. Tries tend to have long chains of single-child nodes, as seen in the example above with f-i-t-l in fitler. So to save space, we use a different format to encode chains than branching nodes. A chain is encoded as a string of keycodes, beginning with the node closest to the root, and terminated with a zero byte. The child of the last node in the chain is encoded immediately after. That child could be either a branching node or a leaf.
In the figure above, the f-i-t-l chain is encoded as
```
+-------+-------+-------+-------+-------+
| L | T | I | F | 0 |
+-------+-------+-------+-------+-------+
```
If we were to encode this chain using the same format used for branching nodes, we would encode a 16-bit node link with every node, costing 8 more bytes in this example. Across the whole trie, this adds up. Conveniently, we can point to intermediate points in the chain and interpret the bytes in the same way as before. E.g. starting at the i instead of the l, and the subchain has the same format.
**Leaf node**. A leaf node corresponds to a particular typo and stores data to correct the typo. The leaf begins with a byte for the number of backspaces to type, and is followed by a null-terminated ASCII string of the replacement text. The idea is, after tapping backspace the indicated number of times, we can simply pass this string to the `send_string_P` function. For fitler, we need to tap backspace 3 times (not 4, because we catch the typo as the final r is pressed) and replace it with lter. To identify the node as a leaf, the two high bits are set to 10 by ORing the backspace count with 128:
```
+-------+-------+-------+-------+-------+-------+
| 3|128 | 'l' | 't' | 'e' | 'r' | 0 |
+-------+-------+-------+-------+-------+-------+
```
### Decoding :id=decoding
This format is by design decodable with fairly simple logic. A 16-bit variable state represents our current position in the trie, initialized with 0 to start at the root node. Then, for each keycode, test the highest two bits in the byte at state to identify the kind of node.
* 00 ⇒ **chain node**: If the nodes byte matches the keycode, increment state by one to go to the next byte. If the next byte is zero, increment again to go to the following node.
* 01 ⇒ **branching node**: Search the branches for one that matches the keycode, and follow its node link.
* 10 ⇒ **leaf node**: a typo has been found! We read its first byte for the number of backspaces to type, then pass its following bytes to send_string_P to type the correction.
## Credits
Credit goes to [getreuer](https://github.com/getreuer) for originally implementing this [here](https://getreuer.info/posts/keyboards/autocorrection/#how-does-it-work). As well as to [filterpaper](https://github.com/filterpaper) for converting the code to use PROGMEM, and additional improvements.

View file

@ -16,15 +16,15 @@ BACKLIGHT_ENABLE = yes
Once enabled, the following keycodes below can be used to change the backlight level.
|Key |Description |
|---------|-----------------------------------|
|`BL_TOGG`|Turn the backlight on or off |
|`BL_STEP`|Cycle through backlight levels |
|`BL_ON` |Set the backlight to max brightness|
|`BL_OFF` |Turn the backlight off |
|`BL_INC` |Increase the backlight level |
|`BL_DEC` |Decrease the backlight level |
|`BL_BRTG`|Toggle backlight breathing |
| Key | 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 |
## Functions :id=functions

View file

@ -39,8 +39,8 @@ BLUETOOTH_DRIVER = BluefruitLE # or RN42
This is used when multiple keyboard outputs can be selected. Currently this only allows for switching between USB and Bluetooth on keyboards that support both.
|Name |Description |
|----------|----------------------------------------------|
|`OUT_AUTO`|Automatically switch between USB and Bluetooth|
|`OUT_USB` |USB only |
|`OUT_BT` |Bluetooth only |
|Key |Aliases |Description |
|---------------------|---------|----------------------------------------------|
|`QK_OUTPUT_AUTO` |`OU_AUTO`|Automatically switch between USB and Bluetooth|
|`QK_OUTPUT_USB` |`OU_USB` |USB only |
|`QK_OUTPUT_BLUETOOTH`|`OU_BT` |Bluetooth only |

View file

@ -4,7 +4,10 @@ It is often useful to type a single word in all capitals, for instance
abbreviations like "QMK", or in code, identifiers like `KC_SPC`. "Caps Word" is
a modern alternative to Caps Lock:
* Letters are capitalized while active, and Caps Word automatically disables
* While active, letters are capitalized and `-` becomes `_`. The `_` makes it easier
to type constant names (eg 'PROGRAM\_CONSTANTS').
* Caps Word automatically disables
itself at the end of the word. That is, it stops by default once a space or
any key other than `KC_A`--`KC_Z`, `KC_0`--`KC_9`, `KC_MINS`, `KC_UNDS`,
`KC_DELETE`, or `KC_BACKSPACE` is pressed. Caps Word also disables itself if
@ -39,8 +42,8 @@ CAPS_WORD_ENABLE = yes
Next, use one the following methods to activate Caps Word:
* **Activate by pressing a key**: Use the `CAPS_WORD` keycode (short
alias `CAPSWRD`) in your keymap.
* **Activate by pressing a key**: Use the `QK_CAPS_WORD_TOGGLE` keycode (short
alias `CW_TOGG`) in your keymap.
* **Activate by pressing Left Shift + Right Shift**: Add `#define
BOTH_SHIFTS_TURNS_ON_CAPS_WORD` to config.h. You may also need to disable or

View file

@ -1,6 +1,6 @@
# Combos
The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the combo term would hit `ESC` instead, or have it perform even more complex tasks.
The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `B` within the combo term would hit `ESC` instead, or have it perform even more complex tasks.
To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`.
@ -20,24 +20,28 @@ combo_t key_combos[COMBO_COUNT] = {
This will send "Escape" if you hit the A and B keys, and Ctrl+Z when you hit the C and D keys.
As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to fire combos from ModTap keys and LayerTap keys. So in the above example you could have keys `LSFT_T(KC_A)` and `LT(_LAYER, KC_B)` and it would work. So Home Row Mods and Home Row Combos at same time is now a thing!
It is also now possible to overlap combos. Before, with the example below both combos would activate when all three keys were pressed. Now only the three key combo will activate.
## Mod-Tap Support
[Mod-Tap](mod_tap.md) feature is also supported together with combos. You will need to use the full Mod-Tap keycode in the combo definition, e.g.:
```c
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), COMBO_END};
const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), KC_C, COMBO_END};
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END};
```
## Overlapping Combos
It is possible to overlap combos. Before, with the example below both combos would activate when all three keys were pressed. Now only the three key combo will activate.
```c
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END};
const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(1, KC_B), KC_C, COMBO_END};
combo_t key_combos[COMBO_COUNT] = {
COMBO(test_combo1, KC_ESC)
COMBO(test_combo2, KC_TAB)
};
```
Executing more complex keycodes like ModTaps and LayerTaps is now also possible.
## Examples
If you want to add a list, then you'd use something like this:
A long list of combos can be defined in an `enum` list that ends with `COMBO_LENGTH` and you can leave `COMBO_COUNT` undefined:
```c
enum combos {
@ -45,7 +49,9 @@ enum combos {
JK_TAB,
QW_SFT,
SD_LAYER,
COMBO_LENGTH
};
uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead!
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
@ -55,13 +61,12 @@ const uint16_t PROGMEM sd_combo[] = {KC_S, KC_D, COMBO_END};
combo_t key_combos[COMBO_COUNT] = {
[AB_ESC] = COMBO(ab_combo, KC_ESC),
[JK_TAB] = COMBO(jk_combo, KC_TAB),
[QW_SFT] = COMBO(qw_combo, KC_LSFT)
[QW_SFT] = COMBO(qw_combo, KC_LSFT),
[SD_LAYER] = COMBO(sd_combo, MO(_LAYER)),
};
```
For a more complicated implementation, you can use the `process_combo_event` function to add custom handling.
Additionally, this example shows how you can leave `COMBO_COUNT` undefined.
```c
enum combo_events {
@ -105,19 +110,19 @@ It is worth noting that `COMBO_ACTION`s are not needed anymore. As of [PR#8591](
## Keycodes
You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game. The following keycodes are available for use in your `keymap.c`
|Keycode |Description |
|----------|---------------------------------|
|`CMB_ON` |Turns on Combo feature |
|`CMB_OFF` |Turns off Combo feature |
|`CMB_TOG` |Toggles Combo feature on and off |
|Keycode |Aliases |Description |
|-----------------|---------|--------------------------------|
|`QK_COMBO_ON` |`CM_ON` |Turns on Combo feature |
|`QK_COMBO_OFF` |`CM_OFF` |Turns off Combo feature |
|`QK_COMBO_TOGGLE`|`CM_TOGG`|Toggles Combo feature on and off|
# Advanced Configuration
## Advanced Configuration
These configuration settings can be set in your `config.h` file.
## Combo Term
### Combo Term
By default, the timeout for the Combos to be recognized is set to 50ms. This can be changed if accidental combo misfires are happening or if you're having difficulties pressing keys at the same time. For instance, `#define COMBO_TERM 40` would set the timeout period for combos to 40ms.
## Buffer and state sizes
### Buffer and state sizes
If you're using long combos, or you have a lot of overlapping combos, you may run into issues with this, as the buffers may not be large enough to accommodate what you're doing. In this case, you can configure the sizes of the buffers used. Be aware, larger combo sizes and larger buffers will increase memory usage!
To configure the amount of keys a combo can be composed of, change the following:
@ -138,13 +143,13 @@ Processing combos has two buffers, one for the key presses, another for the comb
| `#define COMBO_KEY_BUFFER_LENGTH 8` | 8 (the key amount `(EXTRA_)EXTRA_LONG_COMBOS` gives) |
| `#define COMBO_BUFFER_LENGTH 4` | 4 |
## Modifier Combos
### Modifier Combos
If a combo resolves to a Modifier, the window for processing the combo can be extended independently from normal combos. By default, this is disabled but can be enabled with `#define COMBO_MUST_HOLD_MODS`, and the time window can be configured with `#define COMBO_HOLD_TERM 150` (default: `TAPPING_TERM`). With `COMBO_MUST_HOLD_MODS`, you cannot tap the combo any more which makes the combo less prone to misfires.
## Strict key press order
### Strict key press order
By defining `COMBO_MUST_PRESS_IN_ORDER` combos only activate when the keys are pressed in the same order as they are defined in the key array.
## Per Combo Timing, Holding, Tapping and Key Press Order
### Per Combo Timing, Holding, Tapping and Key Press Order
For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, if it needs to be tapped, or if its keys need to be pressed in order.
For example, tap-only combos are useful if any (or all) of the underlying keys are mod-tap or layer-tap keys. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't activate. Instead the keys are processed separately as if the combo wasn't even there.
@ -234,7 +239,7 @@ bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) {
}
```
## Generic hook to (dis)allow a combo activation
### Generic hook to (dis)allow a combo activation
By defining `COMBO_SHOULD_TRIGGER` and its companying function `bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record)` you can block or allow combos to activate on the conditions of your choice.
For example, you could disallow some combos on the base layer and allow them on another. Or disable combos on the home row when a timer is running.
@ -254,8 +259,8 @@ bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode
}
```
## Variable Length Combos
If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = sizeof(key_combos) / sizeof(key_combos[0]);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such:
### Variable Length Combos
If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = ARRAY_SIZE(key_combos);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such:
```c
enum myCombos {
...,
@ -266,26 +271,26 @@ uint16_t COMBO_LEN = COMBO_LENGTH;
Regardless of the method used to declare `COMBO_LEN`, this also requires to convert the `combo_t key_combos[COMBO_COUNT] = {...};` line to `combo_t key_combos[] = {...};`.
## Combo timer
### Combo timer
Normally, the timer is started on the first key press and then reset on every subsequent key press within the `COMBO_TERM`.
Inputting combos is relaxed like this, but also slightly more prone to accidental misfires.
The next two options alter the behaviour of the timer.
### `#define COMBO_STRICT_TIMER`
#### `#define COMBO_STRICT_TIMER`
With `COMBO_STRICT_TIMER`, the timer is started only on the first key press.
Inputting combos is now less relaxed; you need to make sure the full chord is pressed within the `COMBO_TERM`.
Misfires are less common but if you type multiple combos fast, there is a
chance that the latter ones might not activate properly.
### `#define COMBO_NO_TIMER`
#### `#define COMBO_NO_TIMER`
By defining `COMBO_NO_TIMER`, the timer is disabled completely and combos are activated on the first key release.
This also disables the "must hold" functionalities as they just wouldn't work at all.
## Customizable key releases
### Customizable key releases
By defining `COMBO_PROCESS_KEY_RELEASE` and implementing the function `bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode)`, you can run your custom code on each key release after a combo was activated. For example you could change the RGB colors, activate haptics, or alter the modifiers.
@ -322,12 +327,57 @@ bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key
return false;
}
```
## Layer independent combos
### Layer independent combos
If you, for example, use multiple base layers for different key layouts, one for QWERTY, and another one for Colemak, you might want your combos to work from the same key positions on all layers. Defining the same combos again for another layout is redundant and takes more memory. The solution is to just check the keycodes from one layer.
With `#define COMBO_ONLY_FROM_LAYER 0` in config.h, the combos' keys are always checked from layer `0`, even if other layers are active.
#### Combo reference layers by layer.
If not using `COMBO_ONLY_FROM_LAYER` it is possible to specify a
combo reference layer for any layer using the `combo_ref_from_layer` hook.
The combo macros automatically create this function from the `COMBO_REF_LAYER()`
entries given.
This function returns the assigned reference layer for the current layer.
if there is no match, it returns the default reference layer if set,
or the current layer otherwise. A default layer can be set with
`DEFAULT_REF_LAYER(_MY_COMBO_REF_LAYER)`
If not set, the default reference layer selection from the automatically generated
`combo-ref-from-layer()` will be the current layer.
The following `combo_ref_from_layer` function
will give a reference layer of _QWERTY for the _DVORAK layer and
will give the _NAV layer as a reference to it's self. All other layers
will have the default for their combo reference layer. If the default
is not set, all other layers will reference themselves.
```c
#define COMBO_REF_DEFAULT _MY_COMBO_LAYER
...
uint8_t combo_ref_from_layer(uint8_t layer){
switch (get_highest_layer(layer_state)){
case _DVORAK: return _QWERTY;
case _NAV: return _NAV;
default: return _MY_COMBO_LAYER;
}
return layer; // important if default is not in case.
}
```
The equivalent definition using the combo macros is this:
```c
COMBO_REF_LAYER(_DVORAK, _QWERTY)
COMBO_REF_LAYER(_NAV, _NAV)
DEFAULT_REF_LAYER(_MY_COMBO_LAYER).
```
## User callbacks
In addition to the keycodes, there are a few functions that you can use to set the status, or check it:
@ -340,7 +390,7 @@ In addition to the keycodes, there are a few functions that you can use to set t
| `is_combo_enabled()` | Returns the status of the combo feature state (true or false) |
# Dictionary Management
## Dictionary Management
Having 3 places to update when adding new combos or altering old ones does become cumbersome when you have a lot of combos. We can alleviate this with some magic! ... If you consider C macros magic.
First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, include the file `g/keymap_combo.h` in your `keymap.c`.
@ -350,6 +400,11 @@ First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, in
Then, write your combos in `combos.def` file in the following manner:
```c
// Alternate reference layers by layer
// Layer Reference layer
COMBO_REF_LAYER(_DVORAK, _QWERTY) // reference the qwerty layer for dvorak.
COMBO_REF_LAYER(_NAV, _NAV) // explicit reference to self instead of the default.
// name result chord keys
COMB(AB_ESC, KC_ESC, KC_A, KC_B)
COMB(JK_TAB, KC_TAB, KC_J, KC_K)

View file

@ -17,6 +17,15 @@ Currently the following converters are available:
| `promicro` | `bit_c_pro` |
| `promicro` | `stemcell` |
| `promicro` | `bonsai_c4` |
| `promicro` | `elite_pi` |
| `promicro` | `rp2040_ce` |
| `promicro` | `elite_pi` |
| `promicro` | `helios` |
| `promicro` | `michi` |
| `elite_c` | `stemcell` |
| `elite_c` | `rp2040_ce` |
| `elite_c` | `elite_pi` |
| `elite_c` | `helios` |
See below for more in depth information on each converter.
@ -47,6 +56,23 @@ Once a converter is enabled, it exposes the `CONVERT_TO_<target_uppercase>` flag
#endif
```
### Pin Compatibility
To ensure compatibility, provide validation, and power future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`.
Currently the following pin compatibility interfaces are defined:
| Pinout | Notes |
|------------|-----------------------------------|
| `promicro` | Includes RX/TX LEDs |
| `elite_c` | Includes bottom row pins, no LEDs |
To declare the base for conversions, add this line to your keyboard's `rules.mk`:
```makefile
PIN_COMPATIBLE = elite_c
```
## Pro Micro
If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.com/products/12640) (or compatible board), the supported alternative controllers are:
@ -60,6 +86,9 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
| [Bit-C PRO](https://nullbits.co/bit-c-pro) | `bit_c_pro` |
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
| [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
Converter summary:
@ -72,6 +101,10 @@ Converter summary:
| `bit_c_pro` | `-e CONVERT_TO=bit_c_pro` | `CONVERT_TO=bit_c_pro` | `#ifdef CONVERT_TO_BIT_C_PRO` |
| `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` |
| `bonsai_c4` | `-e CONVERT_TO=bonsai_c4` | `CONVERT_TO=bonsai_c4` | `#ifdef CONVERT_TO_BONSAI_C4` |
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
### Proton C :id=proton_c
@ -102,9 +135,9 @@ The following defaults are based on what has been implemented for [RP2040](platf
| USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) |
| [Split keyboards](feature_split_keyboard.md) | Partial via `PIO` vendor driver - heavily dependent on enabled features |
### SparkFun Pro Micro - RP2040, Blok, and Bit-C PRO :id=promicro_rp2040
### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi :id=promicro_rp2040
Currently identical to [Adafruit KB2040](#kb2040).
Currently identical to [Adafruit KB2040](#kb2040).
### STeMCell :id=stemcell
@ -131,8 +164,41 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
```c
#undef B0
// If Vbus detection is unused, we can send RXLED to the Vbus detect pin instead
// If VBUS detection is unused, we can send RXLED to the Vbus detect pin instead
#define B0 PAL_LINE(GPIOA, 9)
```
No peripherals are enabled by default at this time, but example code to enable SPI, I2C, PWM, and Serial communications can be found [here](/keyboards/custommk/bonsai_c4_template)
### RP2040 Community Edition - Elite-Pi and Helios :id=rp2040_ce
Feature set currently identical to [Adafruit KB2040](#kb2040).
Enables VBUS detection by default for superior split keyboard support.
For more information, refer to the [RP2040 Community Edition](platformdev_rp2040.md#rp2040_ce) docs.
## Elite-C
If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products/elite-c-low-profile-version-usb-c-pro-micro-replacement-atmega32u4), the supported alternative controllers are:
| Device | Target |
|----------------------------------------------------------------------------------|-------------------|
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
Converter summary:
| Target | Argument | `rules.mk` | Condition |
|-------------------|---------------------------------|------------------------------|-------------------------------------|
| `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` |
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
### STeMCell :id=stemcell_elite
Currently identical to [STeMCell](#stemcell) with support for the additional bottom row of pins.
### RP2040 Community Edition :id=rp2040_ce_elite
Currently identical to [RP2040 Community Edition](#rp2040_ce), with support for the additional bottom row of pins.

View file

@ -1,35 +1,117 @@
## Digitizer
# Digitizer :id=digitizer
The digitizer HID interface allows setting the mouse cursor position at absolute coordinates, unlike the Pointing Device feature that applies relative displacements.
Digitizers allow the mouse cursor to be placed at absolute coordinates, unlike the [Pointing Device](feature_pointing_device.md) feature which applies relative displacements.
To enable the digitizer interface, add the following line to your rules.mk:
This feature implements a stylus device with a tip switch and barrel switch (generally equivalent to the primary and secondary mouse buttons respectively). Tip pressure is not currently implemented.
## Usage :id=usage
Add the following to your `rules.mk`:
```make
DIGITIZER_ENABLE = yes
```
In order to change the mouse cursor position from your keymap.c file, include the digitizer header :
## Positioning :id=positioning
The X and Y coordinates are normalized, meaning their value must be set between 0 and 1. For the X component, the value `0` is the leftmost position, whereas the value `1` is the rightmost position. Similarly for the Y component, `0` is at the top and `1` at the bottom.
?> Since there is no display attached, the OS will likely map these coordinates to the virtual desktop. This may be important to know if you have multiple monitors.
## Examples :id=examples
This example simply places the cursor in the middle of the screen:
```c
#include "digitizer.h"
digitizer_in_range_on();
digitizer_set_position(0.5, 0.5);
```
This gives you access to the `digitizer` structure which members allow you to change the cursor position.
The "in range" indicator is required to be on for the change in coordinates to be taken. It can then be turned off again to signal the end of the digitizer interaction, but it is not strictly required.
The coordinates are normalized, meaning there value must be set between 0 and 1. For the `x` coordinate, the value `0` is the leftmost position, whereas the value `1` is the rightmost position.
For the `y` coordinate, `0` is at the top and `1` at the bottom.
Here is an example setting the cursor in the middle of the screen:
You can also modify the digitizer state directly, if you need to change multiple fields in a single report:
```c
digitizer_t digitizer;
digitizer.x = 0.5;
digitizer.y = 0.5;
digitizer.tipswitch = 0;
digitizer.inrange = 1;
digitizer_set_report(digitizer);
digitizer_state.in_range = true;
digitizer_state.dirty = true;
digitizer_flush();
```
The `tipswitch` member triggers what equates to a click when set to `1`. The `inrange` member is required for the change in coordinates to be taken. It can then be set to `0` in a new report to signal the end of the digitizer interaction, but it is not strictly required.
`digitizer_state` is a struct of type `digitizer_t`.
Once all members are set to the desired value, the `status` member needs its bitmask `DZ_UPDATED` to be set so the report is sent during the next main loop iteration.
## API :id=api
### `struct digitizer_t` :id=api-digitizer-t
Contains the state of the digitizer.
#### Members :id=api-digitizer-t-members
- `bool in_range`
Indicates to the host that the contact is within range (ie. close to or in contact with the digitizer surface).
- `bool tip`
The state of the tip switch.
- `bool barrel`
The state of the barrel switch.
- `float x`
The X coordinate of the digitizer contact.
- `float y`
The Y coordinate of the digitizer contact.
- `bool dirty`
Whether the current state needs to be sent to the host.
---
### `void digitizer_flush(void)` :id=api-digitizer-flush
Send the digitizer report to the host if it is marked as dirty.
---
### `void digitizer_in_range_on(void)` :api-digitizer-in-range-on
Assert the "in range" indicator, and flush the report.
---
### `void digitizer_in_range_off(void)` :api-digitizer-in-range-off
Deassert the "in range" indicator, and flush the report.
---
### `void digitizer_tip_switch_on(void)` :api-digitizer-tip-switch-on
Assert the tip switch, and flush the report.
---
### `void digitizer_tip_switch_off(void)` :api-digitizer-tip-switch-off
Deassert the tip switch, and flush the report.
---
### `void digitizer_barrel_switch_on(void)` :api-digitizer-barrel-switch-on
Assert the barrel switch, and flush the report.
---
### `void digitizer_barrel_switch_off(void)` :api-digitizer-barrel-switch-off
Deassert the barrel switch, and flush the report.
---
### `void digitizer_set_position(float x, float y)` :api-digitizer-set-position
Set the absolute X and Y position of the digitizer contact, and flush the report.
#### Arguments :id=api-digitizer-set-position-arguments
- `float x`
The X value of the contact position, from 0 to 1.
- `float y`
The Y value of the contact position, from 0 to 1.

View file

@ -6,21 +6,21 @@ You can store one or two macros and they may have a combined total of 128 keypre
To enable them, first include `DYNAMIC_MACRO_ENABLE = yes` in your `rules.mk`. Then, add the following keys to your keymap:
|Key |Alias |Description |
|------------------|----------|---------------------------------------------------|
|`DYN_REC_START1` |`DM_REC1` |Start recording Macro 1 |
|`DYN_REC_START2` |`DM_REC2` |Start recording Macro 2 |
|`DYN_MACRO_PLAY1` |`DM_PLY1` |Replay Macro 1 |
|`DYN_MACRO_PLAY2` |`DM_PLY2` |Replay Macro 2 |
|`DYN_REC_STOP` |`DM_RSTP` |Finish the macro that is currently being recorded. |
|Key |Alias |Description |
|---------------------------------|---------|--------------------------------------------------|
|`QK_DYNAMIC_MACRO_RECORD_START_1`|`DM_REC1`|Start recording Macro 1 |
|`QK_DYNAMIC_MACRO_RECORD_START_2`|`DM_REC2`|Start recording Macro 2 |
|`QK_DYNAMIC_MACRO_PLAY_1` |`DM_PLY1`|Replay Macro 1 |
|`QK_DYNAMIC_MACRO_PLAY_2` |`DM_PLY2`|Replay Macro 2 |
|`QK_DYNAMIC_MACRO_RECORD_STOP` |`DM_RSTP`|Finish the macro that is currently being recorded.|
That should be everything necessary.
To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`.
To start recording the macro, press either `DM_REC1` or `DM_REC2`.
To finish the recording, press the `DYN_REC_STOP` layer button. You can also press `DYN_REC_START1` or `DYN_REC_START2` again to stop the recording.
To finish the recording, press the `DM_RSTP` layer button. You can also press `DM_REC1` or `DM_REC2` again to stop the recording.
To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`.
To replay the macro, press either `DM_PLY1` or `DM_PLY2`.
It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completely by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file.
@ -43,10 +43,10 @@ If the LEDs start blinking during the recording with each keypress, it means the
### DYNAMIC_MACRO_USER_CALL
For users of the earlier versions of dynamic macros: It is still possible to finish the macro recording using just the layer modifier used to access the dynamic macro keys, without a dedicated `DYN_REC_STOP` key. If you want this behavior back, add `#define DYNAMIC_MACRO_USER_CALL` to your `config.h` and insert the following snippet at the beginning of your `process_record_user()` function:
For users of the earlier versions of dynamic macros: It is still possible to finish the macro recording using just the layer modifier used to access the dynamic macro keys, without a dedicated `DM_RSTP` key. If you want this behavior back, add `#define DYNAMIC_MACRO_USER_CALL` to your `config.h` and insert the following snippet at the beginning of your `process_record_user()` function:
```c
uint16_t macro_kc = (keycode == MO(_DYN) ? DYN_REC_STOP : keycode);
uint16_t macro_kc = (keycode == MO(_DYN) ? DM_RSTP : keycode);
if (!process_record_dynamic_macro(macro_kc, record)) {
return false;

134
docs/feature_eeprom.md Normal file
View file

@ -0,0 +1,134 @@
# Persistent Configuration (EEPROM)
This allows you to configure persistent settings for your keyboard. These settings are stored in the EEPROM of your controller, and are retained even after power loss. The settings can be read with `eeconfig_read_kb` and `eeconfig_read_user`, and can be written to using `eeconfig_update_kb` and `eeconfig_update_user`. This is useful for features that you want to be able to toggle (like toggling rgb layer indication). Additionally, you can use `eeconfig_init_kb` and `eeconfig_init_user` to set the default values for the EEPROM.
The complicated part here, is that there are a bunch of ways that you can store and access data via EEPROM, and there is no "correct" way to do this. However, you only have a DWORD (4 bytes) for each function.
Keep in mind that EEPROM has a limited number of writes. While this is very high, it's not the only thing writing to the EEPROM, and if you write too often, you can potentially drastically shorten the life of your MCU.
* If you don't understand the example, then you may want to avoid using this feature, as it is rather complicated.
## Example Implementation
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here. This is a complex function, and has a lot going on. In fact, it uses a lot of the above functions to work!
In your keymap.c file, add this to the top:
```c
typedef union {
uint32_t raw;
struct {
bool rgb_layer_change :1;
};
} user_config_t;
user_config_t user_config;
```
This sets up a 32 bit structure that we can store settings with in memory, and write to the EEPROM. Using this removes the need to define variables, since they're defined in this structure. Remember that `bool` (boolean) values use 1 bit, `uint8_t` uses 8 bits, `uint16_t` uses up 16 bits. You can mix and match, but changing the order can cause issues, as it will change the values that are read and written.
We're using `rgb_layer_change`, for the `layer_state_set_*` function, and use `keyboard_post_init_user` and `process_record_user` to configure everything.
Now, using the `keyboard_post_init_user` code above, you want to add `eeconfig_read_user()` to it, to populate the structure you've just created. And you can then immediately use this structure to control functionality in your keymap. And It should look like:
```c
void keyboard_post_init_user(void) {
// Call the keymap level matrix init.
// Read the user config from EEPROM
user_config.raw = eeconfig_read_user();
// Set default layer, if enabled
if (user_config.rgb_layer_change) {
rgblight_enable_noeeprom();
rgblight_sethsv_noeeprom(HSV_CYAN);
rgblight_mode_noeeprom(1);
}
}
```
The above function will use the EEPROM config immediately after reading it, to set the default layer's RGB color. The "raw" value of it is converted in a usable structure based on the "union" that you created above.
```c
layer_state_t layer_state_set_user(layer_state_t state) {
switch (get_highest_layer(state)) {
case _RAISE:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom(HSV_MAGENTA); rgblight_mode_noeeprom(1); }
break;
case _LOWER:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom(HSV_RED); rgblight_mode_noeeprom(1); }
break;
case _PLOVER:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom(HSV_GREEN); rgblight_mode_noeeprom(1); }
break;
case _ADJUST:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom(HSV_WHITE); rgblight_mode_noeeprom(1); }
break;
default: // for any other layers, or the default layer
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom(HSV_CYAN); rgblight_mode_noeeprom(1); }
break;
}
return state;
}
```
This will cause the RGB underglow to be changed ONLY if the value was enabled. Now to configure this value, create a new keycode for `process_record_user` called `RGB_LYR`. Additionally, we want to make sure that if you use the normal RGB codes, that it turns off Using the example above, make it look this:
```c
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case FOO:
if (record->event.pressed) {
// Do something when pressed
} else {
// Do something else when release
}
return false; // Skip all further processing of this key
case KC_ENTER:
// Play a tone when enter is pressed
if (record->event.pressed) {
PLAY_SONG(tone_qwerty);
}
return true; // Let QMK send the enter press/release events
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
if (record->event.pressed) {
user_config.rgb_layer_change ^= 1; // Toggles the status
eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
if (user_config.rgb_layer_change) { // if layer state indication is enabled,
layer_state_set(layer_state); // then immediately update the layer color
}
}
return false;
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
if (user_config.rgb_layer_change) { // only if this is enabled
user_config.rgb_layer_change = false; // disable it, and
eeconfig_update_user(user_config.raw); // write the setings to EEPROM
}
}
return true; break;
default:
return true; // Process all other keycodes normally
}
}
```
And lastly, you want to add the `eeconfig_init_user` function, so that when the EEPROM is reset, you can specify default values, and even custom actions. To force an EEPROM reset, use the `EE_CLR` keycode or [Bootmagic Lite](feature_bootmagic.md) functionallity. For example, if you want to set rgb layer indication by default, and save the default valued.
```c
void eeconfig_init_user(void) { // EEPROM is getting reset!
user_config.raw = 0;
user_config.rgb_layer_change = true; // We want this enabled by default
eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
// use the non noeeprom versions, to write these values to EEPROM too
rgblight_enable(); // Enable RGB by default
rgblight_sethsv(HSV_CYAN); // Set it to CYAN by default
rgblight_mode(1); // set to solid by default
}
```
And you're done. The RGB layer indication will only work if you want it to. And it will be saved, even after unplugging the board. And if you use any of the RGB codes, it will disable the layer indication, so that it stays on the mode and color that you set it to.
## 'EECONFIG' Function Documentation
* Keyboard/Revision: `void eeconfig_init_kb(void)`, `uint32_t eeconfig_read_kb(void)` and `void eeconfig_update_kb(uint32_t val)`
* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.

View file

@ -1,6 +1,6 @@
# Encoders
Basic encoders are supported by adding this to your `rules.mk`:
Basic (EC11 compatible) encoders are supported by adding this to your `rules.mk`:
```make
ENCODER_ENABLE = yes
@ -67,6 +67,8 @@ Additionally, if one side does not have an encoder, you can specify `{}` for the
#define ENCODER_RESOLUTIONS_RIGHT { 4 }
```
!> Keep in mind that whenver you change the encoder resolution, you will need to reflash the half that has the encoder affected by the change.
## Encoder map :id=encoder-map
Encoder mapping may be added to your `keymap.c`, which replicates the normal keyswitch layer handling functionality, but with encoders. Add this to your keymap's `rules.mk`:
@ -90,13 +92,39 @@ const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
?> This should only be enabled at the keymap level.
Using encoder mapping pumps events through the normal QMK keycode processing pipeline, resulting in a _keydown/keyup_ combination pushed through `process_record_xxxxx()`. To configure the amount of time between the encoder "keyup" and "keydown", you can add the following to your `config.h`:
```c
#define ENCODER_MAP_KEY_DELAY 10
```
?> By default, the encoder map delay matches the value of `TAP_CODE_DELAY`.
## Callbacks
When not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
?> Those who are adding new keyboard support where encoders are enabled at the keyboard level should include basic encoder functionality at the keyboard level (`<keyboard>.c`) using the `encoder_update_kb()` function, that way it works for QMK Configuator users and exists in general.
```c
bool encoder_update_kb(uint8_t index, bool clockwise) {
return encoder_update_user(index, clockwise);
if (!encoder_update_user(index, clockwise)) {
return false; /* Don't process further events if user function exists and returns false */
}
if (index == 0) { /* First encoder */
if (clockwise) {
tap_code_delay(KC_VOLU, 10);
} else {
tap_code_delay(KC_VOLD, 10);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
rgb_matrix_increase_hue();
} else {
rgb_matrix_decrease_hue();
}
}
return true;
}
```
@ -121,49 +149,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
```
!> If you return `true`, it will allow the keyboard level code to run as well. Returning `false` will override the keyboard level code, depending on how the keyboard function is set up.
Layer conditions can also be used with the callback function like the following:
```c
bool encoder_update_user(uint8_t index, bool clockwise) {
switch(get_highest_layer(layer_state|default_layer_state)) {
case 0:
if (index == 0) {
if (clockwise) {
tap_code(KC_PGDN);
} else {
tap_code(KC_PGUP);
}
} else if (index == 1) {
if (clockwise) {
rgb_matrix_increase_speed();
} else {
rgb_matrix_decrease_speed();
}
}
break;
case 1:
if (index == 0) {
if (clockwise) {
tap_code(KC_WH_D);
} else {
tap_code(KC_WH_U);
}
} else if (index == 1) {
if (clockwise) {
tap_code_delay(KC_VOLU, 10);
} else {
tap_code_delay(KC_VOLD, 10);
}
}
break;
}
return false;
}
```
?> Media and mouse countrol keycodes such as `KC_VOLU` and `KC_WH_D` requires `EXTRAKEY_ENABLE = yes` and `MOUSEKEY_ENABLE = yes` respectively in user's `rules.mk` if they are not enabled as default on keyboard level configuration.
!> If you return `true` in the keymap level `_user` function, it will allow the keyboard level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
## Hardware
@ -174,7 +160,7 @@ The A an B lines of the encoders should be wired directly to the MCU, and the C/
Multiple encoders may share pins so long as each encoder has a distinct pair of pins when the following conditions are met:
- using detent encoders
- pads must be high at the detent stability point which is called 'default position' in QMK
- no more than two encoders sharing a pin can be turned at the same time
- no more than two encoders sharing a pin can be turned at the same time
For example you can support two encoders using only 3 pins like this
```
@ -187,4 +173,4 @@ You could even support three encoders using only three pins (one per encoder) ho
#define ENCODERS_PAD_A { B1, B1, B2 }
#define ENCODERS_PAD_B { B2, B3, B3 }
```
Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case
Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case

View file

@ -32,21 +32,21 @@ The following `config.h` settings are available for all types of haptic feedback
Not all keycodes below will work depending on which haptic mechanism you have chosen.
| Name | Description |
|-----------|-------------------------------------------------------|
|`HPT_ON` | Turn haptic feedback on |
|`HPT_OFF` | Turn haptic feedback off |
|`HPT_TOG` | Toggle haptic feedback on/off |
|`HPT_RST` | Reset haptic feedback config to default |
|`HPT_FBK` | Toggle feedback to occur on keypress, release or both |
|`HPT_BUZ` | Toggle solenoid buzz on/off |
|`HPT_MODI` | Go to next DRV2605L waveform |
|`HPT_MODD` | Go to previous DRV2605L waveform |
|`HPT_CONT` | Toggle continuous haptic mode on/off |
|`HPT_CONI` | Increase DRV2605L continous haptic strength |
|`HPT_COND` | Decrease DRV2605L continous haptic strength |
|`HPT_DWLI` | Increase Solenoid dwell time |
|`HPT_DWLD` | Decrease Solenoid dwell time |
| Key | Aliases | Description |
|-----------------------------|---------|-------------------------------------------------------|
|`QK_HAPTIC_ON` |`HF_ON` | Turn haptic feedback on |
|`QK_HAPTIC_OFF` |`HF_OFF` | Turn haptic feedback off |
|`QK_HAPTIC_TOGGLE` |`HF_TOGG`| Toggle haptic feedback on/off |
|`QK_HAPTIC_RESET` |`HF_RST` | Reset haptic feedback config to default |
|`QK_HAPTIC_FEEDBACK_TOGGLE` |`HF_FDBK`| Toggle feedback to occur on keypress, release or both |
|`QK_HAPTIC_BUZZ_TOGGLE` |`HF_BUZZ`| Toggle solenoid buzz on/off |
|`QK_HAPTIC_MODE_NEXT` |`HF_NEXT`| Go to next DRV2605L waveform |
|`QK_HAPTIC_MODE_PREVIOUS` |`HF_PREV`| Go to previous DRV2605L waveform |
|`QK_HAPTIC_CONTINUOUS_TOGGLE`|`HF_CONT`| Toggle continuous haptic mode on/off |
|`QK_HAPTIC_CONTINUOUS_UP` |`HF_CONU`| Increase DRV2605L continous haptic strength |
|`QK_HAPTIC_CONTINUOUS_DOWN` |`HF_COND`| Decrease DRV2605L continous haptic strength |
|`QK_HAPTIC_DWELL_UP` |`HF_DWLU`| Increase Solenoid dwell time |
|`QK_HAPTIC_DWELL_DOWN` |`HF_DWLD`| Decrease Solenoid dwell time |
### Solenoids
@ -68,8 +68,8 @@ For relay switches, the hardware may already contain all of that ciruitry, and j
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the switch. |
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
|`SOLENOID_DWELL_STEP_SIZE` | `1` ms |The step size to use when `HPT_DWL*` keycodes are sent. |
|`SOLENOID_DEFAULT_BUZZ` | `0` (disabled) |On HPT_RST buzz is set "on" if this is "1" |
|`SOLENOID_DWELL_STEP_SIZE` | `1` ms |The step size to use when `HF_DWL*` keycodes are sent. |
|`SOLENOID_DEFAULT_BUZZ` | `0` (disabled) |On `HF_RST` buzz is set "on" if this is "1" |
|`SOLENOID_BUZZ_ACTUATED` | `SOLENOID_MIN_DWELL` |Actuated-time when the switch is in buzz mode. |
|`SOLENOID_BUZZ_NONACTUATED` | `SOLENOID_MIN_DWELL` |Non-Actuated-time when the switch is in buzz mode. |
@ -178,7 +178,7 @@ If haptic feedback is enabled, the keyboard will vibrate to a specific sequence
```
#define DRV_MODE_DEFAULT *sequence name or number*
```
This will set what sequence HPT_RST will set as the active mode. If not defined, mode will be set to 1 when HPT_RST is pressed.
This will set what sequence `HF_RST` will set as the active mode. If not defined, mode will be set to 1 when `HF_RST` is pressed.
### DRV2605L Continuous Haptic Mode

View file

@ -1,154 +1,228 @@
## Joystick
# Joystick :id=joystick
The keyboard can be made to be recognized as a joystick HID device by the operating system.
This feature provides game controller input as a joystick device supporting up to 6 axes and 32 buttons. Axes can be read either from an [ADC-capable input pin](adc_driver.md), or can be virtual, so that its value is provided by your code.
!> Joystick support is not currently available on V-USB devices.
An analog device such as a [potentiometer](https://en.wikipedia.org/wiki/Potentiometer) found on an analog joystick's axes is based on a voltage divider, where adjusting the movable wiper controls the output voltage which can then be read by the microcontroller's ADC.
The joystick feature provides two services:
* reading analog input devices (eg. potentiometers)
* sending gamepad HID reports
## Usage :id=usage
Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance)
or send gamepad reports based on values computed by the keyboard.
### Analog Input
To use analog input you must first enable it in `rules.mk`:
Add the following to your `rules.mk`:
```make
JOYSTICK_ENABLE = yes
JOYSTICK_DRIVER = analog # or 'digital'
```
An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider).
It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor,
which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter).
Depending on which pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated,
feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures.
By default the joystick driver is `analog`, but you can change this with:
### Configuring the Joystick
```make
JOYSTICK_DRIVER = digital
```
By default, two axes and eight buttons are defined. This can be changed in your `config.h`:
## Configuration :id=configuration
By default, two axes and eight buttons are defined, with a reported resolution of 8 bits (-127 to +127). This can be changed in your `config.h`:
```c
// Max 32
// Min 0, max 32
#define JOYSTICK_BUTTON_COUNT 16
// Max 6: X, Y, Z, Rx, Ry, Rz
#define JOYSTICK_AXES_COUNT 3
// Min 0, max 6: X, Y, Z, Rx, Ry, Rz
#define JOYSTICK_AXIS_COUNT 3
// Min 8, max 16
#define JOYSTICK_AXIS_RESOLUTION 10
```
When defining axes for your joystick, you have to provide a definition array. You can do this from your keymap.c file.
A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code.
You have to define an array of type ''joystick_config_t'' and of proper size.
?> You must define at least one button or axis. Also note that the maximum ADC resolution of the supported AVR MCUs is 10-bit, and 12-bit for most STM32 MCUs.
There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU:
* 1 pin: your analog device is directly connected to your device GND and VCC. The only pin used is the ADC pin of your choice.
* 2 pins: your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC.
* 3 pins: both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards.
### Axes :id=axes
The configuration of each axis is performed using one of four macros:
* `JOYSTICK_AXIS_VIRTUAL`: no ADC reading must be performed, that value will be provided by keyboard/keymap-level code
* `JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH)`: a voltage will be read on the provided pin, which must be an ADC-capable pin.
* `JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH)`: the provided `OUTPUT_PIN` will be set high before `INPUT_PIN` is read.
* `JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH)`: the `OUTPUT_PIN` will be set high and `GROUND_PIN` will be set low before reading from `INPUT_PIN`.
When defining axes for your joystick, you must provide a definition array typically in your `keymap.c`.
In any case where an ADC reading takes place (when `INPUT_PIN` is provided), additional `LOW`, `REST` and `HIGH` parameters are used.
These implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127).
In practice, you have to provide the lowest/highest raw ADC reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted `LOW` and `HIGH` to invert the axis.
For instance, an axes configuration can be defined in the following way:
For instance, the below example configures two axes. The X axis is read from the `A4` pin. With the default axis resolution of 8 bits, the range of values between 900 and 575 are scaled to -127 through 0, and values 575 to 285 are scaled to 0 through 127. The Y axis is configured as a virtual axis, and its value is not read from any pin. Instead, the user must update the axis value programmatically.
```c
//joystick config
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
[0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285),
[1] = JOYSTICK_AXIS_VIRTUAL
joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
JOYSTICK_AXIS_IN(A4, 900, 575, 285),
JOYSTICK_AXIS_VIRTUAL
};
```
When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read.
Axes can be configured using one of the following macros:
In this example, the first axis will be read from the `A4` pin while `B0` is set high and `A7` is set low, using `analogReadPin()`, whereas the second axis will not be read.
* `JOYSTICK_AXIS_IN(input_pin, low, rest, high)`
The ADC samples the provided pin. `low`, `high` and `rest` correspond to the minimum, maximum, and resting (or centered) analog values of the axis, respectively.
* `JOYSTICK_AXIS_IN_OUT(input_pin, output_pin, low, rest, high)`
Same as `JOYSTICK_AXIS_IN()`, but the provided `output_pin` will be pulled high before `input_pin` is read.
* `JOYSTICK_AXIS_IN_OUT_GROUND(input_pin, output_pin, ground_pin, low, rest, high)`
Same as `JOYSTICK_AXIS_IN_OUT()`, but the provided `ground_pin` will be pulled low before reading from `input_pin`.
* `JOYSTICK_AXIS_VIRTUAL`
No ADC reading is performed. The value should be provided by user code.
In order to give a value to the second axis, you can do so in any customizable entry point: as an action, in `process_record_user()` or in `matrix_scan_user()`, or even in `joystick_task()` which is called even when no key has been pressed.
You assign a value by writing to `joystick_status.axes[axis_index]` a signed 8-bit value (ranging from -127 to 127). Then it is necessary to assign the flag `JS_UPDATED` to `joystick_status.status` in order for an updated HID report to be sent.
The `low` and `high` values can be swapped to effectively invert the axis.
The following example writes two axes based on keypad presses, with `KC_P5` as a precision modifier:
#### Virtual Axes :id=virtual-axes
The following example adjusts two virtual axes (X and Y) based on keypad presses, with `KC_P0` as a precision modifier:
```c
#ifdef ANALOG_JOYSTICK_ENABLE
static uint8_t precision_val = 70;
static uint8_t axesFlags = 0;
enum axes {
Precision = 1,
Axis1High = 2,
Axis1Low = 4,
Axis2High = 8,
Axis2Low = 16
joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
JOYSTICK_AXIS_VIRTUAL, // x
JOYSTICK_AXIS_VIRTUAL // y
};
#endif
static bool precision = false;
static uint16_t precision_mod = 64;
static uint16_t axis_val = 127;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
#ifdef ANALOG_JOYSTICK_ENABLE
// virtual joystick
# if JOYSTICK_AXES_COUNT > 1
int16_t precision_val = axis_val;
if (precision) {
precision_val -= precision_mod;
}
switch (keycode) {
case KC_P8:
if (record->event.pressed) {
axesFlags |= Axis2Low;
} else {
axesFlags &= ~Axis2Low;
}
joystick_status.status |= JS_UPDATED;
break;
joystick_set_axis(1, record->event.pressed ? -precision_val : 0);
return false;
case KC_P2:
if (record->event.pressed) {
axesFlags |= Axis2High;
} else {
axesFlags &= ~Axis2High;
}
joystick_status.status |= JS_UPDATED;
break;
# endif
joystick_set_axis(1, record->event.pressed ? precision_val : 0);
return false;
case KC_P4:
if (record->event.pressed) {
axesFlags |= Axis1Low;
} else {
axesFlags &= ~Axis1Low;
}
joystick_status.status |= JS_UPDATED;
break;
joystick_set_axis(0, record->event.pressed ? -precision_val : 0);
return false;
case KC_P6:
if (record->event.pressed) {
axesFlags |= Axis1High;
} else {
axesFlags &= ~Axis1High;
}
joystick_status.status |= JS_UPDATED;
break;
case KC_P5:
if (record->event.pressed) {
axesFlags |= Precision;
} else {
axesFlags &= ~Precision;
}
joystick_status.status |= JS_UPDATED;
break;
#endif
joystick_set_axis(0, record->event.pressed ? precision_val : 0);
return false;
case KC_P0:
precision = record->event.pressed;
return false;
}
return true;
}
```
### Axis Resolution
## Keycodes :id=keycodes
By default, the resolution of each axis is 8 bit, giving a range of -127 to +127. If you need higher precision, you can increase it by defining eg. `JOYSTICK_AXES_RESOLUTION 12` in your `config.h`. The resolution must be between 8 and 16.
|Key |Aliases|Description|
|-----------------------|-------|-----------|
|`QK_JOYSTICK_BUTTON_0` |`JS_0` |Button 0 |
|`QK_JOYSTICK_BUTTON_1` |`JS_1` |Button 1 |
|`QK_JOYSTICK_BUTTON_2` |`JS_2` |Button 2 |
|`QK_JOYSTICK_BUTTON_3` |`JS_3` |Button 3 |
|`QK_JOYSTICK_BUTTON_4` |`JS_4` |Button 4 |
|`QK_JOYSTICK_BUTTON_5` |`JS_5` |Button 5 |
|`QK_JOYSTICK_BUTTON_6` |`JS_6` |Button 6 |
|`QK_JOYSTICK_BUTTON_7` |`JS_7` |Button 7 |
|`QK_JOYSTICK_BUTTON_8` |`JS_8` |Button 8 |
|`QK_JOYSTICK_BUTTON_9` |`JS_9` |Button 9 |
|`QK_JOYSTICK_BUTTON_10`|`JS_10`|Button 10 |
|`QK_JOYSTICK_BUTTON_11`|`JS_11`|Button 11 |
|`QK_JOYSTICK_BUTTON_12`|`JS_12`|Button 12 |
|`QK_JOYSTICK_BUTTON_13`|`JS_13`|Button 13 |
|`QK_JOYSTICK_BUTTON_14`|`JS_14`|Button 14 |
|`QK_JOYSTICK_BUTTON_15`|`JS_15`|Button 15 |
|`QK_JOYSTICK_BUTTON_16`|`JS_16`|Button 16 |
|`QK_JOYSTICK_BUTTON_17`|`JS_17`|Button 17 |
|`QK_JOYSTICK_BUTTON_18`|`JS_18`|Button 18 |
|`QK_JOYSTICK_BUTTON_19`|`JS_19`|Button 19 |
|`QK_JOYSTICK_BUTTON_20`|`JS_20`|Button 20 |
|`QK_JOYSTICK_BUTTON_21`|`JS_21`|Button 21 |
|`QK_JOYSTICK_BUTTON_22`|`JS_22`|Button 22 |
|`QK_JOYSTICK_BUTTON_23`|`JS_23`|Button 23 |
|`QK_JOYSTICK_BUTTON_24`|`JS_24`|Button 24 |
|`QK_JOYSTICK_BUTTON_25`|`JS_25`|Button 25 |
|`QK_JOYSTICK_BUTTON_26`|`JS_26`|Button 26 |
|`QK_JOYSTICK_BUTTON_27`|`JS_27`|Button 27 |
|`QK_JOYSTICK_BUTTON_28`|`JS_28`|Button 28 |
|`QK_JOYSTICK_BUTTON_29`|`JS_29`|Button 29 |
|`QK_JOYSTICK_BUTTON_30`|`JS_30`|Button 30 |
|`QK_JOYSTICK_BUTTON_31`|`JS_31`|Button 31 |
Note that the supported AVR MCUs have a 10-bit ADC, and 12-bit for most STM32 MCUs.
## API :id=api
### Triggering Joystick Buttons
### `struct joystick_t` :id=api-joystick-t
Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured.
To trigger a joystick button, just add the corresponding keycode to your keymap.
Contains the state of the joystick.
You can also trigger joystick buttons in code with `register_joystick_button(button)` and `unregister_joystick_button(button)`, where `button` is the 0-based button index (0 = button 1).
#### Members :id=api-joystick-t-members
- `uint8_t buttons[]`
A bit-packed array containing the joystick button states. The size is calculated as `(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1`.
- `int16_t axes[]`
An array of analog values for each defined axis.
- `bool dirty`
Whether the current state needs to be sent to the host.
---
### `struct joystick_config_t` :id=api-joystick-config-t
Describes a single axis.
#### Members :id=api-joystick-config-t-members
- `pin_t output_pin`
A pin to set as output high when reading the analog value, or `JS_VIRTUAL_AXIS`.
- `pin_t input_pin`
The pin to read the analog value from, or `JS_VIRTUAL_AXIS`.
- `pin_t ground_pin`
A pin to set as output low when reading the analog value, or `JS_VIRTUAL_AXIS`.
- `uint16_t min_digit`
The minimum analog value.
- `uint16_t mid_digit`
The resting or midpoint analog value.
- `uint16_t max_digit`
The maximum analog value.
---
### `void joystick_flush(void)` :id=api-joystick-flush
Send the joystick report to the host, if it has been marked as dirty.
---
### `void register_joystick_button(uint8_t button)` :id=api-register-joystick-button
Set the state of a button, and flush the report.
#### Arguments :id=api-register-joystick-button-arguments
- `uint8_t button`
The index of the button to press, from 0 to 31.
---
### `void unregister_joystick_button(uint8_t button)` :id=api-unregister-joystick-button
Reset the state of a button, and flush the report.
#### Arguments :id=api-unregister-joystick-button-arguments
- `uint8_t button`
The index of the button to release, from 0 to 31.
---
### `int16_t joystick_read_axis(uint8_t axis)` :id=api-joystick-read-axis
Sample and process the analog value of the given axis.
#### Arguments :id=api-joystick-read-axis-arguments
- `uint8_t axis`
The axis to read.
#### Return Value :id=api-joystick-read-axis-return
A signed 16-bit integer, where 0 is the resting or mid point.
### `void joystick_set_axis(uint8_t axis, int16_t value)` :id=api-joystick-set-axis
Set the value of the given axis.
#### Arguments :id=api-joystick-set-axis-arguments
- `uint8_t axis`
The axis to set the value of.
- `int16_t value`
The value to set.

View file

@ -2,21 +2,21 @@
Sometimes you may find yourself needing to hold down a specific key for a long period of time. Key Lock holds down the next key you press for you. Press it again, and it will be released.
Let's say you need to type in ALL CAPS for a few sentences. Hit `KC_LOCK`, and then Shift. Now, Shift will be considered held until you tap it again. You can think of Key Lock as Caps Lock, but supercharged.
Let's say you need to type in ALL CAPS for a few sentences. Hit `QK_LOCK`, and then Shift. Now, Shift will be considered held until you tap it again. You can think of Key Lock as Caps Lock, but supercharged.
## Usage
First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Then pick a key in your keymap and assign it the keycode `KC_LOCK`.
First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Then pick a key in your keymap and assign it the keycode `QK_LOCK`.
## Keycodes
|Keycode |Description |
|---------|--------------------------------------------------------------|
|`KC_LOCK`|Hold down the next key pressed, until the key is pressed again|
|`QK_LOCK`|Hold down the next key pressed, until the key is pressed again|
## Caveats
Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(MOD_LSFT)`).
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
Switching layers will not cancel the Key Lock. The Key Lock can be cancelled by calling the `cancel_key_lock()` function.

View file

@ -150,15 +150,13 @@ const key_override_t fn_override = {.trigger_mods = MOD_BIT(KC_RGUI) |
.enabled = NULL};
```
## Keycodes
## Keycodes
You can enable, disable and toggle all key overrides on the fly.
|Keycode |Description |Function Equivalent|
|----------|---------------------------------|--------|
|`KEY_OVERRIDE_ON` |Turns on Key Override feature | `key_override_on(void)`|
|`KEY_OVERRIDE_OFF` |Turns off Key Override feature |`key_override_off(void)`|
|`KEY_OVERRIDE_TOGGLE` |Toggles Key Override feature on and off |`key_override_toggle(void)`|
|Keycode |Aliases |Description |
|------------------------|---------|----------------------|
|`QK_KEY_OVERRIDE_TOGGLE`|`KO_TOGG`|Toggle key overrides |
|`QK_KEY_OVERRIDE_ON` |`KO_ON` |Turn on key overrides |
|`QK_KEY_OVERRIDE_OFF` |`KO_OFF` |Turn off key overrides|
## Reference for `key_override_t`

View file

@ -1,6 +1,6 @@
# Layers :id=layers
One of the most powerful and well used features of QMK Firmware is the ability to use layers. For most people, this amounts to a function key that allows for different keys, much like what you would see on a laptop or tablet keyboard.
One of the most powerful and well used features of QMK Firmware is the ability to use layers. For most people, this amounts to a function key that allows for different keys, much like what you would see on a laptop or tablet keyboard.
For a detailed explanation of how the layer stack works, checkout [Keymap Overview](keymap.md#keymap-and-layers).
@ -9,8 +9,8 @@ For a detailed explanation of how the layer stack works, checkout [Keymap Overvi
These functions allow you to activate layers in various ways. Note that layers are not generally independent layouts -- multiple layers can be activated at once, and it's typical for layers to use `KC_TRNS` to allow keypresses to pass through to lower layers. When using momentary layer switching with MO(), LM(), TT(), or LT(), make sure to leave the key on the above layers transparent or it may not work as intended.
* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).)
* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated.
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated.
* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15. The modifiers this keycode accept are prefixed with `MOD_`, not `KC_`. These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`.
* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15.
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys.md) for details and additional functionality.
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
@ -21,6 +21,12 @@ These functions allow you to activate layers in various ways. Note that layers a
Currently, the `layer` argument of `LT()` is limited to layers 0-15, and the `kc` argument to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. This is because QMK uses 16-bit keycodes, of which 4 bits are used for the function identifier and 4 bits for the layer, leaving only 8 bits for the keycode.
For a similar reason, the `layer` argument of `LM()` is also limited to layers 0-15 and the `mod` argument must fit within 5 bits. As a consequence, although left and right modifiers are supported by `LM()`, it is impossible to mix and match left and right modifiers. Specifying at least one right-hand modifier in a combination such as `MOD_RALT|MOD_LSFT` will convert *all* the listed modifiers to their right-hand counterpart. So, using the aforementionned mod-mask will actually send <kbd>Right Alt</kbd>+<kbd>Right Shift</kbd>. Make sure to use the `MOD_xxx` constants over alternative ways of specifying modifiers when defining your layer-mod key.
| `LM(1,KC_LSFT)` | `LM(1,MOD_MASK_SHIFT)` | `LM(1,MOD_BIT(KC_LSFT))` | `LM(1,MOD_LSFT)` |
|:---------------:|:----------------------:|:------------------------:|:----------------:|
| ❌ | ❌ | ❌ | ✅ |
Expanding this would be complicated, at best. Moving to a 32-bit keycode would solve a lot of this, but would double the amount of space that the keymap matrix uses. And it could potentially cause issues, too. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this.
## Working with Layers :id=working-with-layers
@ -31,7 +37,7 @@ Care must be taken when switching layers, it's possible to lock yourself into a
If you are just getting started with QMK you will want to keep everything simple. Follow these guidelines when setting up your layers:
* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number).
* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number).
* Arrange your layers in a "tree" layout, with layer 0 as the root. Do not try to enter the same layer from more than one other layer.
* In a layer's keymap, only reference higher-numbered layers. Because layers are processed from the highest-numbered (topmost) active layer down, modifying the state of lower layers can be tricky and error-prone.
@ -53,7 +59,7 @@ There are a number of functions (and variables) related to how you can use or ma
|Function |Description |
|----------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `layer_state_set(layer_mask)` | Directly sets the layer state (recommended, do not use unless you know what you are doing). |
| `layer_state_set(layer_mask)` | Directly sets the layer state (avoid unless you know what you are doing). |
| `layer_clear()` | Clears all layers (turns them all off). |
| `layer_move(layer)` | Turns specified layer on, and all other layers off. |
| `layer_on(layer)` | Turns specified layer on, leaves all other layers in existing state. |
@ -63,7 +69,7 @@ There are a number of functions (and variables) related to how you can use or ma
| `layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing layer state. |
| `layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing layer state. |
| `layer_debug(layer_mask)` | Prints out the current bit mask and highest active layer to debugger console. |
| `default_layer_set(layer_mask)` | Directly sets the default layer state (recommended, do not use unless you know what you are doing). |
| `default_layer_set(layer_mask)` | Directly sets the default layer state (avoid unless you know what you are doing). |
| `default_layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing default layer state. |
| `default_layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing default layer state. |
| `default_layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing default layer state. |
@ -89,3 +95,46 @@ It is also possible to check the state of a particular layer using the following
|---------------------------------|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| `layer_state_is(layer)` | Checks if the specified `layer` is enabled globally. | `IS_LAYER_ON(layer)`, `IS_LAYER_OFF(layer)` |
| `layer_state_cmp(state, layer)` | Checks `state` to see if the specified `layer` is enabled. Intended for use in layer callbacks. | `IS_LAYER_ON_STATE(state, layer)`, `IS_LAYER_OFF_STATE(state, layer)` |
## Layer Change Code :id=layer-change-code
This runs code every time that the layers get changed. This can be useful for layer indication, or custom layer handling.
### Example `layer_state_set_*` Implementation
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example.
```c
layer_state_t layer_state_set_user(layer_state_t state) {
switch (get_highest_layer(state)) {
case _RAISE:
rgblight_setrgb (0x00, 0x00, 0xFF);
break;
case _LOWER:
rgblight_setrgb (0xFF, 0x00, 0x00);
break;
case _PLOVER:
rgblight_setrgb (0x00, 0xFF, 0x00);
break;
case _ADJUST:
rgblight_setrgb (0x7A, 0x00, 0xFF);
break;
default: // for any other layers, or the default layer
rgblight_setrgb (0x00, 0xFF, 0xFF);
break;
}
return state;
}
```
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
### `layer_state_set_*` Function Documentation
* Keyboard/Revision: `layer_state_t layer_state_set_kb(layer_state_t state)`
* Keymap: `layer_state_t layer_state_set_user(layer_state_t state)`
The `state` is the bitmask of the active layers, as explained in the [Keymap Overview](keymap.md#keymap-layer-status)

View file

@ -1,159 +1,297 @@
# The Leader Key: A New Kind of Modifier
# The Leader Key: A New Kind of Modifier :id=the-leader-key
If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.
If you're a Vim user, you probably know what a Leader key is. In contrast to [Combos](feature_combo.md), the Leader key allows you to hit a *sequence* of up to five keys instead, which triggers some custom functionality once complete.
That's what `KC_LEAD` does. Here's an example:
## Usage :id=usage
1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low.
* By default, this timeout is how long after pressing `KC_LEAD` to complete your entire sequence. This may be very low for some people. So you may want to increase this timeout. Optionally, you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. This allows you to maintain a low value here, but still be able to use the longer sequences. To enable this option, add `#define LEADER_PER_KEY_TIMING` to your `config.h`.
3. Within your `matrix_scan_user` function, add something like this:
```c
LEADER_EXTERNS();
void matrix_scan_user(void) {
LEADER_DICTIONARY() {
leading = false;
leader_end();
SEQ_ONE_KEY(KC_F) {
// Anything you can do in a macro.
SEND_STRING("QMK is awesome.");
}
SEQ_TWO_KEYS(KC_D, KC_D) {
SEND_STRING(SS_LCTL("a") SS_LCTL("c"));
}
SEQ_THREE_KEYS(KC_D, KC_D, KC_S) {
SEND_STRING("https://start.duckduckgo.com\n");
}
SEQ_TWO_KEYS(KC_A, KC_S) {
register_code(KC_LGUI);
register_code(KC_S);
unregister_code(KC_S);
unregister_code(KC_LGUI);
}
}
}
```
As you can see, you have a few functions. You can use `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS`, `SEQ_THREE_KEYS` up to `SEQ_FIVE_KEYS` for longer sequences.
Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously.
## Adding Leader Key Support in the `rules.mk`
To add support for Leader Key you simply need to add a single line to your keymap's `rules.mk`:
Add the following to your `rules.mk`:
```make
LEADER_ENABLE = yes
```
## Per Key Timing on Leader keys
Then add the `QK_LEAD` keycode to your keymap.
Rather than relying on an incredibly high timeout for long leader key strings or those of us without 200wpm typing skills, we can enable per key timing to ensure that each key pressed provides us with more time to finish our stroke. This is incredibly helpful with leader key emulation of tap dance (read: multiple taps of the same key like C, C, C).
## Callbacks :id=callbacks
These callbacks are invoked when the leader sequence begins and ends. In the latter you can implement your custom functionality based on the contents of the sequence buffer.
```c
void leader_start_user(void) {
// Do something when the leader key is pressed
}
void leader_end_user(void) {
if (leader_sequence_one_key(KC_F)) {
// Leader, f => Types the below string
SEND_STRING("QMK is awesome.");
} else if (leader_sequence_two_keys(KC_D, KC_D)) {
// Leader, d, d => Ctrl+A, Ctrl+C
SEND_STRING(SS_LCTL("a") SS_LCTL("c"));
} else if (leader_sequence_three_keys(KC_D, KC_D, KC_S)) {
// Leader, d, d, s => Types the below string
SEND_STRING("https://start.duckduckgo.com\n");
} else if (leader_sequence_two_keys(KC_A, KC_S)) {
// Leader, a, s => GUI+S
tap_code16(LGUI(KC_S));
}
}
```
## Basic Configuration :id=basic-configuration
### Timeout :id=timeout
This is the amount of time you have to complete a sequence once the leader key has been pressed. The default value is 300 milliseconds, but you can change this by adding the following to your `config.h`:
```c
#define LEADER_TIMEOUT 350
```
### Per-Key Timeout :id=per-key-timeout
Rather than relying on an incredibly high timeout for long leader key strings or those of us without 200 wpm typing skills, you can enable per-key timing to ensure that each key pressed provides you with more time to finish the sequence. This is incredibly helpful with leader key emulation of tap dance (such as multiple taps of the same key like C, C, C).
To enable this, add the following to your `config.h`:
In order to enable this, place this in your `config.h`:
```c
#define LEADER_PER_KEY_TIMING
```
After this, it's recommended that you lower your `LEADER_TIMEOUT` to something less that 300ms.
After this, it's recommended that you lower your timeout below 300 ms:
```c
#define LEADER_TIMEOUT 250
```
Now, something like this won't seem impossible to do without a 1000MS leader key timeout:
Now, something like this won't seem impossible to do without a 1000 millisecond timeout:
```c
SEQ_THREE_KEYS(KC_C, KC_C, KC_C) {
SEND_STRING("Per key timing is great!!!");
if (leader_sequence_three_keys(KC_C, KC_C, KC_C)) {
SEND_STRING("Per key timing is great!!!");
}
```
## Infinite Leader key timeout
### Disabling Initial Timeout :id=disabling-initial-timeout
Sometimes your leader key is not on a comfortable place as the rest of keys on your sequence. Imagine that your leader key is one of your outer top right keys, you may need to reposition your hand just to reach your leader key.
This can make typing the entire sequence on time hard even if you are able to type most of the sequence fast. For example, if your sequence is `Leader + asd` typing `asd` fast is very easy once you have your hands in your home row. However starting the sequence in time after moving your hand out of the home row to reach the leader key and back is not.
To remove the stress this situation produces to your hands you can enable an infinite timeout just for the leader key. This means that after you hit the leader key you will have an infinite amount of time to start the rest of the sequence, allowing you to proper position your hands on the best position to type the rest of the sequence comfortably.
This infinite timeout only affects the leader key, so in our previous example of `Leader + asd` you will have an infinite amount of time between `Leader` and `a`, but once you start the sequence the timeout you have configured (global or per key) will work normally.
This way you can configure a very short `LEADER_TIMEOUT` but still have plenty of time to position your hands.
Sometimes your leader key may be too far away from the rest of the keys in the sequence. Imagine that your leader key is one of your outer top right keys - you may need to reposition your hand just to reach your leader key. This can make typing the entire sequence on time hard difficult if you are able to type most of the sequence fast. For example, if your sequence is `Leader + asd`, typing `asd` fast is very easy once you have your hands in your home row, but starting the sequence in time after moving your hand out of the home row to reach the leader key and back is not.
To remove the stress this situation produces to your hands, you can disable the timeout just for the leader key. Add the following to your `config.h`:
In order to enable this, place this in your `config.h`:
```c
#define LEADER_NO_TIMEOUT
```
## Strict Key Processing
Now, after you hit the leader key, you will have an infinite amount of time to start the rest of the sequence, allowing you to properly position your hands to type the rest of the sequence comfortably. This way you can configure a very short `LEADER_TIMEOUT`, but still have plenty of time to position your hands.
By default, the Leader Key feature will filter the keycode out of [`Mod-Tap`](mod_tap.md) and [`Layer Tap`](feature_layers.md#switching-and-toggling-layers) functions when checking for the Leader sequences. That means if you're using `LT(3, KC_A)`, it will pick this up as `KC_A` for the sequence, rather than `LT(3, KC_A)`, giving a more expected behavior for newer users.
### Strict Key Processing :id=strict-key-processing
While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by adding `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This will then disable the filtering, and you'll need to specify the whole keycode.
By default, only the "tap keycode" portions of [Mod-Taps](mod_tap.md) and [Layer Taps](feature_layers.md#switching-and-toggling-layers) are added to the sequence buffer. This means if you press eg. `LT(3, KC_A)` as part of a sequence, `KC_A` will be added to the buffer, rather than the entire `LT(3, KC_A)` keycode.
## Customization
This gives a more expected behaviour for most users, however you may want to change this.
The Leader Key feature has some additional customization to how the Leader Key feature works. It has two functions that can be called at certain parts of the process. Namely `leader_start()` and `leader_end()`.
The `leader_start()` function is called when you tap the `KC_LEAD` key, and the `leader_end()` function is called when either the leader sequence is completed, or the leader timeout is hit.
You can add these functions to your code (`keymap.c` usually) to add feedback to the Leader sequences (such as beeping or playing music).
To enable this, add the following to your `config.h`:
```c
void leader_start(void) {
// sequence started
}
void leader_end(void) {
// sequence ended (no success/failure detection)
}
#define LEADER_KEY_STRICT_KEY_PROCESSING
```
### Example
## Example :id=example
This example will play the Mario "One Up" sound when you hit `KC_LEAD` to start the Leader Sequence, and will play "All Star" if it completes successfully or "Rick Roll" you if it fails.
This example will play the Mario "One Up" sound when you hit `QK_LEAD` to start the leader sequence. When the sequence ends, it will play "All Star" if it completes successfully or "Rick Roll" you if it fails (in other words, no sequence matched).
```c
bool did_leader_succeed;
#ifdef AUDIO_ENABLE
float leader_start[][2] = SONG(ONE_UP_SOUND );
float leader_succeed[][2] = SONG(ALL_STAR);
float leader_fail[][2] = SONG(RICK_ROLL);
float leader_start_song[][2] = SONG(ONE_UP_SOUND);
float leader_succeed_song[][2] = SONG(ALL_STAR);
float leader_fail_song[][2] = SONG(RICK_ROLL);
#endif
LEADER_EXTERNS();
void matrix_scan_user(void) {
LEADER_DICTIONARY() {
did_leader_succeed = leading = false;
void leader_start_user(void) {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_start_song);
#endif
}
SEQ_ONE_KEY(KC_E) {
// Anything you can do in a macro.
SEND_STRING(SS_LCTL(SS_LSFT("t")));
did_leader_succeed = true;
} else
SEQ_TWO_KEYS(KC_E, KC_D) {
SEND_STRING(SS_LGUI("r") "cmd\n" SS_LCTL("c"));
did_leader_succeed = true;
void leader_end_user(void) {
bool did_leader_succeed = false;
if (leader_sequence_one_key(KC_E)) {
SEND_STRING(SS_LCTL(SS_LSFT("t")));
did_leader_succeed = true;
} else if (leader_sequence_two_keys(KC_E, KC_D)) {
SEND_STRING(SS_LGUI("r") "cmd\n" SS_LCTL("c"));
did_leader_succeed = true;
}
leader_end();
}
}
void leader_start(void) {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_start);
if (did_leader_succeed) {
PLAY_SONG(leader_succeed_song);
} else {
PLAY_SONG(leader_fail_song);
}
#endif
}
void leader_end(void) {
if (did_leader_succeed) {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_succeed);
#endif
} else {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_fail);
#endif
}
}
```
## Keycodes :id=keycodes
|Key |Aliases |Description |
|-----------------------|---------|-------------------------|
|`QK_LEADER` |`QK_LEAD`|Begin the leader sequence|
## API :id=api
### `void leader_start_user(void)` :id=api-leader-start-user
User callback, invoked when the leader sequence begins.
---
### `void leader_end_user(void)` :id=api-leader-end-user
User callback, invoked when the leader sequence ends.
---
### `void leader_start(void)` :id=api-leader-start
Begin the leader sequence, resetting the buffer and timer.
---
### `void leader_end(void)` :id=api-leader-end
End the leader sequence.
---
### `bool leader_sequence_active(void)` :id=api-leader-sequence-active
Whether the leader sequence is active.
---
### `bool leader_sequence_add(uint16_t keycode)` :id=api-leader-sequence-add
Add the given keycode to the sequence buffer.
If `LEADER_NO_TIMEOUT` is defined, the timer is reset if the buffer is empty.
#### Arguments :id=api-leader-sequence-add-arguments
- `uint16_t keycode`
The keycode to add.
#### Return Value :id=api-leader-sequence-add-return
`true` if the keycode was added, `false` if the buffer is full.
---
### `bool leader_sequence_timed_out(void)` :id=api-leader-sequence-timed-out
Whether the leader sequence has reached the timeout.
If `LEADER_NO_TIMEOUT` is defined, the buffer must also contain at least one key.
---
### `bool leader_reset_timer(void)` :id=api-leader-reset-timer
Reset the leader sequence timer.
---
### `bool leader_sequence_one_key(uint16_t kc)` :id=api-leader-sequence-one-key
Check the sequence buffer for the given keycode.
#### Arguments :id=api-leader-sequence-one-key-arguments
- `uint16_t kc`
The keycode to check.
#### Return Value :id=api-leader-sequence-one-key-return
`true` if the sequence buffer matches.
---
### `bool leader_sequence_two_keys(uint16_t kc1, uint16_t kc2)` :id=api-leader-sequence-two-keys
Check the sequence buffer for the given keycodes.
#### Arguments :id=api-leader-sequence-two-keys-arguments
- `uint16_t kc1`
The first keycode to check.
- `uint16_t kc2`
The second keycode to check.
#### Return Value :id=api-leader-sequence-two-keys-return
`true` if the sequence buffer matches.
---
### `bool leader_sequence_three_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3)` :id=api-leader-sequence-three-keys
Check the sequence buffer for the given keycodes.
#### Arguments :id=api-leader-sequence-three-keys-arguments
- `uint16_t kc1`
The first keycode to check.
- `uint16_t kc2`
The second keycode to check.
- `uint16_t kc3`
The third keycode to check.
#### Return Value :id=api-leader-sequence-three-keys-return
`true` if the sequence buffer matches.
---
### `bool leader_sequence_four_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3, uint16_t kc4)` :id=api-leader-sequence-four-keys
Check the sequence buffer for the given keycodes.
#### Arguments :id=api-leader-sequence-four-keys-arguments
- `uint16_t kc1`
The first keycode to check.
- `uint16_t kc2`
The second keycode to check.
- `uint16_t kc3`
The third keycode to check.
- `uint16_t kc4`
The fourth keycode to check.
#### Return Value :id=api-leader-sequence-four-keys-return
`true` if the sequence buffer matches.
---
### `bool leader_sequence_five_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3, uint16_t kc4, uint16_t kc5)` :id=api-leader-sequence-five-keys
Check the sequence buffer for the given keycodes.
#### Arguments :id=api-leader-sequence-five-keys-arguments
- `uint16_t kc1`
The first keycode to check.
- `uint16_t kc2`
The second keycode to check.
- `uint16_t kc3`
The third keycode to check.
- `uint16_t kc4`
The fourth keycode to check.
- `uint16_t kc5`
The fifth keycode to check.
#### Return Value :id=api-leader-sequence-five-keys-return
`true` if the sequence buffer matches.

View file

@ -19,7 +19,7 @@ There are three ways to get the lock LED state:
Two deprecated functions that provide the LED state as `uint8_t`:
* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
* `uint8_t led_set_user(uint8_t usb_led)`
* `uint8_t host_keyboard_leds()`
## Configuration Options
@ -101,6 +101,13 @@ The `host_keyboard_led_state()` function will report the LED state returned from
bool caps = host_keyboard_led_state().caps_lock;
```
## `led_update_ports()`
This function writes the LED state to the actual hardware. Call it manually
from your `led_update_*()` callbacks to modify the handling of the standard
keyboard LEDs.
For example when repurposing a standard LED indicator as layer indicator.
## Setting Physical LED State
Some keyboard implementations provide convenient methods for setting the state of the physical LEDs.

View file

@ -22,7 +22,7 @@ You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `LED_DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many LED lights are present across all drivers | |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
| `LED_DRIVER_ADDR_1` | (Required) Address for the first LED driver | |
| `LED_DRIVER_ADDR_2` | (Optional) Address for the second LED driver | |
| `LED_DRIVER_ADDR_3` | (Optional) Address for the third LED driver | |
@ -44,17 +44,17 @@ Here is an example using 2 drivers.
#define LED_DRIVER_COUNT 2
#define LED_DRIVER_1_LED_TOTAL 25
#define LED_DRIVER_2_LED_TOTAL 24
#define DRIVER_LED_TOTAL (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)
#define LED_MATRIX_LED_COUNT (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `LED_DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)` will give very different results than `rand() % LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `LED_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)` will give very different results than `rand() % LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL`.
For split keyboards using `LED_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@ -82,7 +82,7 @@ Where `<driver name>` is the applicable LED driver chip as below
| Driver Name | Data Sheet | Capability |
|-------------|------------|------------|
| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 180 LED, 30x6 Matrix |
| `ISSIFL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 198 LED, 18x11 Matrix |
| `IS31FL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 198 LED, 18x11 Matrix |
| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 144 LED, 18x8 Matrix |
| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 72 LED, 18x4 Matrix |
@ -95,7 +95,7 @@ Configure the hardware via your `config.h`:
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many LED lights are present across all drivers | |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first LED driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional LED drivers | |
| `ISSI_SSR_<N>` | (Optional) Configuration for the Spread Spectrum Register | |
@ -130,16 +130,16 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `LED_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led __flash g_is31_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@ -199,7 +199,7 @@ x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
```
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `#define LED_MATRIX_CENTER { 112, 32 }` in their config.h file with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `{ x, y }` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
@ -221,14 +221,14 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{
All LED matrix keycodes are currently shared with the [Backlight feature](feature_backlight.md).
|Key |Description |
|---------|-----------------------------|
|`BL_TOGG`|Toggle LED Matrix on or off |
|`BL_STEP`|Cycle through modes |
|`BL_ON` |Turn on LED Matrix |
|`BL_OFF` |Turn off LED Matrix |
|`BL_INC` |Increase the brightness level|
|`BL_DEC` |Decrease the brightness level|
| Key | Aliases | Description |
|-------------------------|-----------|-------------------------------|
| `QK_BACKLIGHT_TOGGLE` | `BL_TOGG` | Toggle LED Matrix on or off |
| `QK_BACKLIGHT_STEP` | `BL_STEP` | Cycle through modes |
| `QK_BACKLIGHT_ON` | `BL_ON` | Turn on LED Matrix |
| `QK_BACKLIGHT_OFF` | `BL_OFF` | Turn off LED Matrix |
| `QK_BACKLIGHT_UP` | `BL_UP` | Increase the brightness level |
| `QK_BACKLIGHT_DOWN` | `BL_DOWN` | Decrease the brightness level |
## LED Matrix Effects :id=led-matrix-effects
@ -364,15 +364,14 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
#define LED_MATRIX_KEYPRESSES // reacts to keypresses
#define LED_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
#define LED_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
#define LED_DISABLE_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off
#define LED_DISABLE_AFTER_TIMEOUT 0 // OBSOLETE: number of ticks to wait until disabling effects
#define LED_MATRIX_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off
#define LED_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define LED_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
#define LED_MATRIX_LED_PROCESS_LIMIT (LED_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
#define LED_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
#define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs
#define LED_MATRIX_STARTUP_MODE LED_MATRIX_SOLID // Sets the default mode, if none has been set
#define LED_MATRIX_STARTUP_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define LED_MATRIX_STARTUP_SPD 127 // Sets the default animation speed, if none has been set
#define LED_MATRIX_DEFAULT_MODE LED_MATRIX_SOLID // Sets the default mode, if none has been set
#define LED_MATRIX_DEFAULT_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define LED_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define LED_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
// If LED_MATRIX_KEYPRESSES or LED_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
```
@ -391,7 +390,7 @@ Where `28` is an unused index from `eeconfig.h`.
|Function |Description |
|--------------------------------------------|-------------|
|`led_matrix_set_value_all(v)` |Set all of the LEDs to the given value, where `v` is between 0 and 255 (not written to EEPROM) |
|`led_matrix_set_value(index, v)` |Set a single LED to the given value, where `v` is between 0 and 255, and `index` is between 0 and `DRIVER_LED_TOTAL` (not written to EEPROM) |
|`led_matrix_set_value(index, v)` |Set a single LED to the given value, where `v` is between 0 and 255, and `index` is between 0 and `LED_MATRIX_LED_COUNT` (not written to EEPROM) |
### Disable/Enable Effects :id=disable-enable-effects
|Function |Description |
@ -440,10 +439,14 @@ Where `28` is an unused index from `eeconfig.h`.
### Indicators :id=indicators
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `led_matrix_indicators_kb` or `led_matrix_indicators_user` function for that:
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `led_matrix_indicators_kb` or `led_matrix_indicators_user` function for that:
```c
void led_matrix_indicators_kb(void) {
bool led_matrix_indicators_kb(void) {
if (!led_matrix_indicators_user()) {
return false;
}
led_matrix_set_value(index, value);
return true;
}
```
@ -452,5 +455,6 @@ In addition, there are the advanced indicator functions. These are aimed at tho
```c
void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
LED_MATRIX_INDICATOR_SET_VALUE(index, value);
return false;
}
```

View file

@ -33,7 +33,7 @@ You can define up to 32 macros in a `keymap.json` file, as used by [Configurator
],
"layout": "LAYOUT_all",
"layers": [
["MACRO_0", "MACRO_1", "MACRO_2", "MACRO_3"]
["QK_MACRO_0", "QK_MACRO_1", "QK_MACRO_2", "QK_MACRO_3"]
]
}
```
@ -52,7 +52,7 @@ If you type in a language other than English, or use a non-QWERTY layout like Co
],
"layout": "LAYOUT_all",
"layers": [
["MACRO_0"]
["QK_MACRO_0"]
]
}
```
@ -199,7 +199,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#### Advanced Macros
In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance.
In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance.
In this example, we modify most normal keypresses so that `F22` is pressed before the keystroke is normally sent, and release it __only after__ it's been released.
@ -374,7 +374,7 @@ This will clear all keys besides the mods currently pressed.
This macro will register `KC_LALT` and tap `KC_TAB`, then wait for 1000ms. If the key is tapped again, it will send another `KC_TAB`; if there is no tap, `KC_LALT` will be unregistered, thus allowing you to cycle through windows.
```c
bool is_alt_tab_active = false; // ADD this near the begining of keymap.c
bool is_alt_tab_active = false; // ADD this near the beginning of keymap.c
uint16_t alt_tab_timer = 0; // we will be using them soon.
enum custom_keycodes { // Make sure have the awesome keycode ready

View file

@ -60,9 +60,9 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case MIDI_CC80:
if (record->event.pressed) {
midi_send_cc(&midi_device, midi_config.channel, 80, ON);
midi_send_cc(&midi_device, midi_config.channel, 80, MIDI_CC_ON);
} else {
midi_send_cc(&midi_device, midi_config.channel, 80, OFF);
midi_send_cc(&midi_device, midi_config.channel, 80, MIDI_CC_OFF);
}
return true;
}
@ -80,164 +80,164 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
### Keycodes
|Keycode |Aliases |Description |
|------------|---------|---------------------------------|
|`MI_ON` | |Turn MIDI on |
|`MI_OFF` | |Turn MIDI off |
|`MI_TOG` | |Toggle MIDI enabled |
|`MI_C` | |C octave 0 |
|`MI_Cs` |`MI_Db` |C♯/D♭ octave 0 |
|`MI_D` | |D octave 0 |
|`MI_Ds` |`MI_Eb` |D♯/E♭ octave 0 |
|`MI_E` | |E octave 0 |
|`MI_F` | |F octave 0 |
|`MI_Fs` |`MI_Gb` |F♯/G♭ octave 0 |
|`MI_G` | |G octave 0 |
|`MI_Gs` |`MI_Gs` |G♯/A♭ octave 0 |
|`MI_A` | |A octave 0 |
|`MI_As` |`MI_Bb` |A♯/B♭ octave 0 |
|`MI_B` | |B octave 0 |
|`MI_C_1` | |C octave 1 |
|`MI_Cs_1` |`MI_Db_1`|C♯/D♭ octave 1 |
|`MI_D_1` | |D octave 1 |
|`MI_Ds_1` |`MI_Eb_1`|D♯/E♭ octave 1 |
|`MI_E_1` | |E octave 1 |
|`MI_F_1` | |F octave 1 |
|`MI_Fs_1` |`MI_Gb_1`|F♯/G♭ octave 1 |
|`MI_G_1` | |G octave 1 |
|`MI_Gs_1` |`MI_Ab_1`|G♯/A♭ octave 1 |
|`MI_A_1` | |A octave 1 |
|`MI_As_1` |`MI_Bb_1`|A♯/B♭ octave 1 |
|`MI_B_1` | |B octave 1 |
|`MI_C_2` | |C octave 2 |
|`MI_Cs_2` |`MI_Db_2`|C♯/D♭ octave 2 |
|`MI_D_2` | |D octave 2 |
|`MI_Ds_2` |`MI_Eb_2`|D♯/E♭ octave 2 |
|`MI_E_2` | |E octave 2 |
|`MI_F_2` | |F octave 2 |
|`MI_Fs_2` |`MI_Gb_2`|F♯/G♭ octave 2 |
|`MI_G_2` | |G octave 2 |
|`MI_Gs_2` |`MI_Ab_2`|G♯/A♭ octave 2 |
|`MI_A_2` | |A octave 2 |
|`MI_As_2` |`MI_Bb_2`|A♯/B♭ octave 2 |
|`MI_B_2` | |B octave 2 |
|`MI_C_3` | |C octave 3 |
|`MI_Cs_3` |`MI_Db_3`|C♯/D♭ octave 3 |
|`MI_D_3` | |D octave 3 |
|`MI_Ds_3` |`MI_Eb_3`|D♯/E♭ octave 3 |
|`MI_E_3` | |E octave 3 |
|`MI_F_3` | |F octave 3 |
|`MI_Fs_3` |`MI_Gb_3`|F♯/G♭ octave 3 |
|`MI_G_3` | |G octave 3 |
|`MI_Gs_3` |`MI_Ab_3`|G♯/A♭ octave 3 |
|`MI_A_3` | |A octave 3 |
|`MI_As_3` |`MI_Bb_3`|A♯/B♭ octave 3 |
|`MI_B_3` | |B octave 3 |
|`MI_C_4` | |C octave 4 |
|`MI_Cs_4` |`MI_Db_4`|C♯/D♭ octave 4 |
|`MI_D_4` | |D octave 4 |
|`MI_Ds_4` |`MI_Eb_4`|D♯/E♭ octave 4 |
|`MI_E_4` | |E octave 4 |
|`MI_F_4` | |F octave 4 |
|`MI_Fs_4` |`MI_Gb_4`|F♯/G♭ octave 4 |
|`MI_G_4` | |G octave 4 |
|`MI_Gs_4` |`MI_Ab_4`|G♯/A♭ octave 4 |
|`MI_A_4` | |A octave 4 |
|`MI_As_4` |`MI_Bb_4`|A♯/B♭ octave 4 |
|`MI_B_4` | |B octave 4 |
|`MI_C_5` | |C octave 5 |
|`MI_Cs_5` |`MI_Db_5`|C♯/D♭ octave 5 |
|`MI_D_5` | |D octave 5 |
|`MI_Ds_5` |`MI_Eb_5`|D♯/E♭ octave 5 |
|`MI_E_5` | |E octave 5 |
|`MI_F_5` | |F octave 5 |
|`MI_Fs_5` |`MI_Gb_5`|F♯/G♭ octave 5 |
|`MI_G_5` | |G octave 5 |
|`MI_Gs_5` |`MI_Ab_5`|G♯/A♭ octave 5 |
|`MI_A_5` | |A octave 5 |
|`MI_As_5` |`MI_Bb_5`|A♯/B♭ octave 5 |
|`MI_B_5` | |B octave 5 |
|`MI_OCT_N2` | |Set octave to -2 |
|`MI_OCT_N1` | |Set octave to -1 |
|`MI_OCT_0` | |Set octave to 0 |
|`MI_OCT_1` | |Set octave to 1 |
|`MI_OCT_2` | |Set octave to 2 |
|`MI_OCT_3` | |Set octave to 3 |
|`MI_OCT_4` | |Set octave to 4 |
|`MI_OCT_5` | |Set octave to 5 |
|`MI_OCT_6` | |Set octave to 6 |
|`MI_OCT_7` | |Set octave to 7 |
|`MI_OCTD` | |Move down an octave |
|`MI_OCTU` | |Move up an octave |
|`MI_TRNS_N6`| |Set transposition to -6 semitones|
|`MI_TRNS_N5`| |Set transposition to -5 semitones|
|`MI_TRNS_N4`| |Set transposition to -4 semitones|
|`MI_TRNS_N3`| |Set transposition to -3 semitones|
|`MI_TRNS_N2`| |Set transposition to -2 semitones|
|`MI_TRNS_N1`| |Set transposition to -1 semitone |
|`MI_TRNS_0` | |No transposition |
|`MI_TRNS_1` | |Set transposition to +1 semitone |
|`MI_TRNS_2` | |Set transposition to +2 semitones|
|`MI_TRNS_3` | |Set transposition to +3 semitones|
|`MI_TRNS_4` | |Set transposition to +4 semitones|
|`MI_TRNS_5` | |Set transposition to +5 semitones|
|`MI_TRNS_6` | |Set transposition to +6 semitones|
|`MI_TRNSD` | |Decrease transposition |
|`MI_TRNSU` | |Increase transposition |
|`MI_VEL_0` | |Set velocity to 0 |
|`MI_VEL_1` | |Set velocity to 12 |
|`MI_VEL_2` | |Set velocity to 25 |
|`MI_VEL_3` | |Set velocity to 38 |
|`MI_VEL_4` | |Set velocity to 51 |
|`MI_VEL_5` | |Set velocity to 64 |
|`MI_VEL_6` | |Set velocity to 76 |
|`MI_VEL_7` | |Set velocity to 89 |
|`MI_VEL_8` | |Set velocity to 102 |
|`MI_VEL_9` | |Set velocity to 114 |
|`MI_VEL_10` | |Set velocity to 127 |
|`MI_VELD` | |Decrease velocity |
|`MI_VELU` | |Increase velocity |
|`MI_CH1` | |Set channel to 1 |
|`MI_CH2` | |Set channel to 2 |
|`MI_CH3` | |Set channel to 3 |
|`MI_CH4` | |Set channel to 4 |
|`MI_CH5` | |Set channel to 5 |
|`MI_CH6` | |Set channel to 6 |
|`MI_CH7` | |Set channel to 7 |
|`MI_CH8` | |Set channel to 8 |
|`MI_CH9` | |Set channel to 9 |
|`MI_CH10` | |Set channel to 10 |
|`MI_CH11` | |Set channel to 11 |
|`MI_CH12` | |Set channel to 12 |
|`MI_CH13` | |Set channel to 13 |
|`MI_CH14` | |Set channel to 14 |
|`MI_CH15` | |Set channel to 15 |
|`MI_CH16` | |Set channel to 16 |
|`MI_CHD` | |Decrease channel |
|`MI_CHU` | |Increase channel |
|`MI_ALLOFF` | |Stop all notes |
|`MI_SUS` | |Sustain |
|`MI_PORT` | |Portmento |
|`MI_SOST` | |Sostenuto |
|`MI_SOFT` | |Soft Pedal |
|`MI_LEG` | |Legato |
|`MI_MOD` | |Modulation |
|`MI_MODSD` | |Decrease modulation speed |
|`MI_MODSU` | |Increase modulation speed |
|`MI_BENDD` | |Bend pitch down |
|`MI_BENDU` | |Bend pitch up |
|Keycode |Aliases |Description |
|-------------------------------|------------------|---------------------------------|
|`QK_MIDI_ON` |`MI_ON` |Turn MIDI on |
|`QK_MIDI_OFF` |`MI_OFF` |Turn MIDI off |
|`QK_MIDI_TOGGLE` |`MI_TOGG` |Toggle MIDI enabled |
|`QK_MIDI_NOTE_C_0` |`MI_C` |C octave 0 |
|`QK_MIDI_NOTE_C_SHARP_0` |`MI_Cs`, `MI_Db` |C♯/D♭ octave 0 |
|`QK_MIDI_NOTE_D_0` |`MI_D` |D octave 0 |
|`QK_MIDI_NOTE_D_SHARP_0` |`MI_Ds`, `MI_Eb` |D♯/E♭ octave 0 |
|`QK_MIDI_NOTE_E_0` |`MI_E` |E octave 0 |
|`QK_MIDI_NOTE_F_0` |`MI_F` |F octave 0 |
|`QK_MIDI_NOTE_F_SHARP_0` |`MI_Fs`, `MI_Gb` |F♯/G♭ octave 0 |
|`QK_MIDI_NOTE_G_0` |`MI_G` |G octave 0 |
|`QK_MIDI_NOTE_G_SHARP_0` |`MI_Gs`, `MI_Ab` |G♯/A♭ octave 0 |
|`QK_MIDI_NOTE_A_0` |`MI_A` |A octave 0 |
|`QK_MIDI_NOTE_A_SHARP_0` |`MI_As`, `MI_Bb` |A♯/B♭ octave 0 |
|`QK_MIDI_NOTE_B_0` |`MI_B` |B octave 0 |
|`QK_MIDI_NOTE_C_1` |`MI_C1` |C octave 1 |
|`QK_MIDI_NOTE_C_SHARP_1` |`MI_Cs1`, `MI_Db1`|C♯/D♭ octave 1 |
|`QK_MIDI_NOTE_D_1` |`MI_D1` |D octave 1 |
|`QK_MIDI_NOTE_D_SHARP_1` |`MI_Ds1`, `MI_Eb1`|D♯/E♭ octave 1 |
|`QK_MIDI_NOTE_E_1` |`MI_E1` |E octave 1 |
|`QK_MIDI_NOTE_F_1` |`MI_F1` |F octave 1 |
|`QK_MIDI_NOTE_F_SHARP_1` |`MI_Fs1`, `MI_Gb1`|F♯/G♭ octave 1 |
|`QK_MIDI_NOTE_G_1` |`MI_G1` |G octave 1 |
|`QK_MIDI_NOTE_G_SHARP_1` |`MI_Gs1`, `MI_Ab1`|G♯/A♭ octave 1 |
|`QK_MIDI_NOTE_A_1` |`MI_A1` |A octave 1 |
|`QK_MIDI_NOTE_A_SHARP_1` |`MI_As1`, `MI_Bb1`|A♯/B♭ octave 1 |
|`QK_MIDI_NOTE_B_1` |`MI_B1` |B octave 1 |
|`QK_MIDI_NOTE_C_2` |`MI_C2` |C octave 2 |
|`QK_MIDI_NOTE_C_SHARP_2` |`MI_Cs2`, `MI_Db2`|C♯/D♭ octave 2 |
|`QK_MIDI_NOTE_D_2` |`MI_D2` |D octave 2 |
|`QK_MIDI_NOTE_D_SHARP_2` |`MI_Ds2`, `MI_Eb2`|D♯/E♭ octave 2 |
|`QK_MIDI_NOTE_E_2` |`MI_E2` |E octave 2 |
|`QK_MIDI_NOTE_F_2` |`MI_F2` |F octave 2 |
|`QK_MIDI_NOTE_F_SHARP_2` |`MI_Fs2`, `MI_Gb2`|F♯/G♭ octave 2 |
|`QK_MIDI_NOTE_G_2` |`MI_G2` |G octave 2 |
|`QK_MIDI_NOTE_G_SHARP_2` |`MI_Gs2`, `MI_Ab2`|G♯/A♭ octave 2 |
|`QK_MIDI_NOTE_A_2` |`MI_A2` |A octave 2 |
|`QK_MIDI_NOTE_A_SHARP_2` |`MI_As2`, `MI_Bb2`|A♯/B♭ octave 2 |
|`QK_MIDI_NOTE_B_2` |`MI_B2` |B octave 2 |
|`QK_MIDI_NOTE_C_3` |`MI_C3` |C octave 3 |
|`QK_MIDI_NOTE_C_SHARP_3` |`MI_Cs3`, `MI_Db3`|C♯/D♭ octave 3 |
|`QK_MIDI_NOTE_D_3` |`MI_D3` |D octave 3 |
|`QK_MIDI_NOTE_D_SHARP_3` |`MI_Ds3`, `MI_Eb3`|D♯/E♭ octave 3 |
|`QK_MIDI_NOTE_E_3` |`MI_E3` |E octave 3 |
|`QK_MIDI_NOTE_F_3` |`MI_F3` |F octave 3 |
|`QK_MIDI_NOTE_F_SHARP_3` |`MI_Fs3`, `MI_Gb3`|F♯/G♭ octave 3 |
|`QK_MIDI_NOTE_G_3` |`MI_G3` |G octave 3 |
|`QK_MIDI_NOTE_G_SHARP_3` |`MI_Gs3`, `MI_Ab3`|G♯/A♭ octave 3 |
|`QK_MIDI_NOTE_A_3` |`MI_A3` |A octave 3 |
|`QK_MIDI_NOTE_A_SHARP_3` |`MI_As3`, `MI_Bb3`|A♯/B♭ octave 3 |
|`QK_MIDI_NOTE_B_3` |`MI_B3` |B octave 3 |
|`QK_MIDI_NOTE_C_4` |`MI_C4` |C octave 4 |
|`QK_MIDI_NOTE_C_SHARP_4` |`MI_Cs4`, `MI_Db4`|C♯/D♭ octave 4 |
|`QK_MIDI_NOTE_D_4` |`MI_D4` |D octave 4 |
|`QK_MIDI_NOTE_D_SHARP_4` |`MI_Ds4`, `MI_Eb4`|D♯/E♭ octave 4 |
|`QK_MIDI_NOTE_E_4` |`MI_E4` |E octave 4 |
|`QK_MIDI_NOTE_F_4` |`MI_F4` |F octave 4 |
|`QK_MIDI_NOTE_F_SHARP_4` |`MI_Fs4`, `MI_Gb4`|F♯/G♭ octave 4 |
|`QK_MIDI_NOTE_G_4` |`MI_G4` |G octave 4 |
|`QK_MIDI_NOTE_G_SHARP_4` |`MI_Gs4`, `MI_Ab4`|G♯/A♭ octave 4 |
|`QK_MIDI_NOTE_A_4` |`MI_A4` |A octave 4 |
|`QK_MIDI_NOTE_A_SHARP_4` |`MI_As4`, `MI_Bb4`|A♯/B♭ octave 4 |
|`QK_MIDI_NOTE_B_4` |`MI_B4` |B octave 4 |
|`QK_MIDI_NOTE_C_5` |`MI_C5` |C octave 5 |
|`QK_MIDI_NOTE_C_SHARP_5` |`MI_Cs5`, `MI_Db5`|C♯/D♭ octave 5 |
|`QK_MIDI_NOTE_D_5` |`MI_D5` |D octave 5 |
|`QK_MIDI_NOTE_D_SHARP_5` |`MI_Ds5`, `MI_Eb5`|D♯/E♭ octave 5 |
|`QK_MIDI_NOTE_E_5` |`MI_E5` |E octave 5 |
|`QK_MIDI_NOTE_F_5` |`MI_F5` |F octave 5 |
|`QK_MIDI_NOTE_F_SHARP_5` |`MI_Fs5`, `MI_Gb5`|F♯/G♭ octave 5 |
|`QK_MIDI_NOTE_G_5` |`MI_G5` |G octave 5 |
|`QK_MIDI_NOTE_G_SHARP_5` |`MI_Gs5`, `MI_Ab5`|G♯/A♭ octave 5 |
|`QK_MIDI_NOTE_A_5` |`MI_A5` |A octave 5 |
|`QK_MIDI_NOTE_A_SHARP_5` |`MI_As5`, `MI_Bb5`|A♯/B♭ octave 5 |
|`QK_MIDI_NOTE_B_5` |`MI_B5` |B octave 5 |
|`QK_MIDI_OCTAVE_N2` |`MI_OCN2` |Set octave to -2 |
|`QK_MIDI_OCTAVE_N1` |`MI_OCN1` |Set octave to -1 |
|`QK_MIDI_OCTAVE_0` |`MI_OC0` |Set octave to 0 |
|`QK_MIDI_OCTAVE_1` |`MI_OC1` |Set octave to 1 |
|`QK_MIDI_OCTAVE_2` |`MI_OC2` |Set octave to 2 |
|`QK_MIDI_OCTAVE_3` |`MI_OC3` |Set octave to 3 |
|`QK_MIDI_OCTAVE_4` |`MI_OC4` |Set octave to 4 |
|`QK_MIDI_OCTAVE_5` |`MI_OC5` |Set octave to 5 |
|`QK_MIDI_OCTAVE_6` |`MI_OC6` |Set octave to 6 |
|`QK_MIDI_OCTAVE_7` |`MI_OC7` |Set octave to 7 |
|`QK_MIDI_OCTAVE_DOWN` |`MI_OCTD` |Move down an octave |
|`QK_MIDI_OCTAVE_UP` |`MI_OCTU` |Move up an octave |
|`QK_MIDI_TRANSPOSE_N6` |`MI_TRN6` |Set transposition to -6 semitones|
|`QK_MIDI_TRANSPOSE_N5` |`MI_TRN5` |Set transposition to -5 semitones|
|`QK_MIDI_TRANSPOSE_N4` |`MI_TRN4` |Set transposition to -4 semitones|
|`QK_MIDI_TRANSPOSE_N3` |`MI_TRN3` |Set transposition to -3 semitones|
|`QK_MIDI_TRANSPOSE_N2` |`MI_TRN2` |Set transposition to -2 semitones|
|`QK_MIDI_TRANSPOSE_N1` |`MI_TRN1` |Set transposition to -1 semitone |
|`QK_MIDI_TRANSPOSE_0` |`MI_TR0` |No transposition |
|`QK_MIDI_TRANSPOSE_1` |`MI_TR1` |Set transposition to +1 semitone |
|`QK_MIDI_TRANSPOSE_2` |`MI_TR2` |Set transposition to +2 semitones|
|`QK_MIDI_TRANSPOSE_3` |`MI_TR3` |Set transposition to +3 semitones|
|`QK_MIDI_TRANSPOSE_4` |`MI_TR4` |Set transposition to +4 semitones|
|`QK_MIDI_TRANSPOSE_5` |`MI_TR5` |Set transposition to +5 semitones|
|`QK_MIDI_TRANSPOSE_6` |`MI_TR6` |Set transposition to +6 semitones|
|`QK_MIDI_TRANSPOSE_DOWN` |`MI_TRSD` |Decrease transposition |
|`QK_MIDI_TRANSPOSE_UP` |`MI_TRSU` |Increase transposition |
|`QK_MIDI_VELOCITY_0` |`MI_VL0` |Set velocity to 0 |
|`QK_MIDI_VELOCITY_1` |`MI_VL1` |Set velocity to 12 |
|`QK_MIDI_VELOCITY_2` |`MI_VL2` |Set velocity to 25 |
|`QK_MIDI_VELOCITY_3` |`MI_VL3` |Set velocity to 38 |
|`QK_MIDI_VELOCITY_4` |`MI_VL4` |Set velocity to 51 |
|`QK_MIDI_VELOCITY_5` |`MI_VL5` |Set velocity to 64 |
|`QK_MIDI_VELOCITY_6` |`MI_VL6` |Set velocity to 76 |
|`QK_MIDI_VELOCITY_7` |`MI_VL7` |Set velocity to 89 |
|`QK_MIDI_VELOCITY_8` |`MI_VL8` |Set velocity to 102 |
|`QK_MIDI_VELOCITY_9` |`MI_VL9` |Set velocity to 114 |
|`QK_MIDI_VELOCITY_10` |`MI_VL10` |Set velocity to 127 |
|`QK_MIDI_VELOCITY_DOWN` |`MI_VELD` |Decrease velocity |
|`QK_MIDI_VELOCITY_UP` |`MI_VELU` |Increase velocity |
|`QK_MIDI_CHANNEL_1` |`MI_CH1` |Set channel to 1 |
|`QK_MIDI_CHANNEL_2` |`MI_CH2` |Set channel to 2 |
|`QK_MIDI_CHANNEL_3` |`MI_CH3` |Set channel to 3 |
|`QK_MIDI_CHANNEL_4` |`MI_CH4` |Set channel to 4 |
|`QK_MIDI_CHANNEL_5` |`MI_CH5` |Set channel to 5 |
|`QK_MIDI_CHANNEL_6` |`MI_CH6` |Set channel to 6 |
|`QK_MIDI_CHANNEL_7` |`MI_CH7` |Set channel to 7 |
|`QK_MIDI_CHANNEL_8` |`MI_CH8` |Set channel to 8 |
|`QK_MIDI_CHANNEL_9` |`MI_CH9` |Set channel to 9 |
|`QK_MIDI_CHANNEL_10` |`MI_CH10` |Set channel to 10 |
|`QK_MIDI_CHANNEL_11` |`MI_CH11` |Set channel to 11 |
|`QK_MIDI_CHANNEL_12` |`MI_CH12` |Set channel to 12 |
|`QK_MIDI_CHANNEL_13` |`MI_CH13` |Set channel to 13 |
|`QK_MIDI_CHANNEL_14` |`MI_CH14` |Set channel to 14 |
|`QK_MIDI_CHANNEL_15` |`MI_CH15` |Set channel to 15 |
|`QK_MIDI_CHANNEL_16` |`MI_CH16` |Set channel to 16 |
|`QK_MIDI_CHANNEL_DOWN` |`MI_CHND` |Decrease channel |
|`QK_MIDI_CHANNEL_UP` |`MI_CHNU` |Increase channel |
|`QK_MIDI_ALL_NOTES_OFF` |`MI_AOFF` |Stop all notes |
|`QK_MIDI_SUSTAIN` |`MI_SUST` |Sustain |
|`QK_MIDI_PORTAMENTO` |`MI_PORT` |Portmento |
|`QK_MIDI_SOSTENUTO` |`MI_SOST` |Sostenuto |
|`QK_MIDI_SOFT` |`MI_SOFT` |Soft Pedal |
|`QK_MIDI_LEGATO` |`MI_LEG` |Legato |
|`QK_MIDI_MODULATION` |`MI_MOD` |Modulation |
|`QK_MIDI_MODULATION_SPEED_DOWN`|`MI_MODD` |Decrease modulation speed |
|`QK_MIDI_MODULATION_SPEED_UP` |`MI_MODU` |Increase modulation speed |
|`QK_MIDI_PITCH_BEND_DOWN` |`MI_BNDD` |Bend pitch down |
|`QK_MIDI_PITCH_BEND_UP` |`MI_BNDU` |Bend pitch up |
### Configuration
Certain values are stored in the `midi_config` struct. This configuration is not persisted to EEPROM. By default, these values are:
|Configuration |Value|Comments |
|-------------------|-----|-------------------------|
|Octave |`4` |Corresponds to `MI_OCT_2`|
|Transposition |`0` | |
|Velocity |`127`| |
|Channel |`0` | |
|Modulation Interval|`8` | |
|Configuration |Value|Comments |
|-------------------|-----|-----------------------|
|Octave |`4` |Corresponds to `MI_OC2`|
|Transposition |`0` | |
|Velocity |`127`| |
|Channel |`0` | |
|Modulation Interval|`8` | |
For the above, the `MI_C` keycode will produce a C3 (note number 48), and so on.
@ -250,10 +250,10 @@ For the above, the `MI_C` keycode will produce a C3 (note number 48), and so on.
* `quantum/process_keycode/process_midi.c`
* `quantum/quantum_keycodes.h`
* `tmk_core/protocol/midi.h`
* `tmk_core/protocol/midi.c`
* `tmk_core/protocol/qmk_midi.c`
* `tmk_core/protocol/midi_device.h`
* `quantum/midi/midi.h`
* `quantum/midi/midi.c`
* `quantum/midi/qmk_midi.c`
* `quantum/midi/midi_device.h`
<!--
#### QMK Internals (Autogenerated)

View file

@ -45,8 +45,9 @@ Mouse keys supports three different modes to move the cursor:
* **Kinetic:** Holding movement keys accelerates the cursor with its speed following a quadratic curve until it reaches its maximum speed.
* **Constant:** Holding movement keys moves the cursor at constant speeds.
* **Combined:** Holding movement keys accelerates the cursor until it reaches its maximum speed, but holding acceleration and movement keys simultaneously moves the cursor at constant speeds.
* **Inertia:** Cursor accelerates when key held, and decelerates after key release. Tracks X and Y velocity separately for more nuanced movements. Applies to cursor only, not scrolling.
The same principle applies to scrolling.
The same principle applies to scrolling, in most modes.
Configuration options that are times, intervals or delays are given in milliseconds. Scroll speed is given as multiples of the default scroll step. For example, a scroll speed of 8 means that each scroll action covers 8 times the length of the default scroll step as defined by your operating system or application.
@ -167,6 +168,37 @@ To use combined speed mode, you must at least define `MK_COMBINED` in your keyma
#define MK_COMBINED
```
### Inertia mode
This mode provides smooth motion, like sliding on ice. The cursor accelerates
along a quadratic curve while a key is held, then glides to a stop after the
key is released. Vertical and horizontal movements are tracked independently,
so the cursor can move in many directions and make curves.
Cannot be used at the same time as Kinetic mode, Constant mode, or Combined mode.
Recommended settings in your keymaps `config.h` file:
|Define |Default |Description |
|----------------------------|---------|-----------------------------------------------------------|
|`MOUSEKEY_INERTIA` |undefined|Enable Inertia mode |
|`MOUSEKEY_DELAY` |150 |Delay between pressing a movement key and cursor movement |
|`MOUSEKEY_INTERVAL` |16 |Time between cursor movements in milliseconds (16 = 60fps) |
|`MOUSEKEY_MAX_SPEED` |32 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_TIME_TO_MAX` |32 |Number of frames until maximum cursor speed is reached |
|`MOUSEKEY_FRICTION` |24 |How quickly the cursor stops after releasing a key |
|`MOUSEKEY_MOVE_DELTA` |1 |How much to move on first frame (1 strongly recommended) |
Tips:
* Set `MOUSEKEY_DELAY` to roughly the same value as your host computer's key repeat delay, in ms. Recommended values are 100 to 300.
* Set `MOUSEKEY_INTERVAL` to a value of 1000 / your monitor's FPS. For 60 FPS, 1000/60 = 16.
* Set `MOUSEKEY_MAX_SPEED` based on your screen resolution and refresh rate, like Width / FPS. For example, 1920 pixels / 60 FPS = 32 pixels per frame.
* Set `MOUSEKEY_TIME_TO_MAX` to a value of approximately FPS / 2, to make it reach full speed in half a second (or so).
* Set `MOUSEKEY_FRICTION` to something between 1 and 255. Lower makes the cursor glide longer. Values from 8 to 40 are the most effective.
* Keep `MOUSEKEY_MOVE_DELTA` at 1. This allows precise movements before the gliding effect starts.
* Mouse wheel options are the same as the default accelerated mode, and do not use inertia.
## Use with PS/2 Mouse and Pointing Device
Mouse keys button state is shared with [PS/2 mouse](feature_ps2_mouse.md) and [pointing device](feature_pointing_device.md) so mouse keys button presses can be used for clicks and drags.

View file

@ -80,6 +80,11 @@ static void render_logo(void) {
oled_write_P(qmk_logo, false);
}
bool oled_task_user(void) {
render_logo();
return false;
}
```
?> The default font file is located at `drivers/oled/glcdfont.c` and its location can be overwritten with the `OLED_FONT_H` configuration option. Font file content can be edited with external tools such as [Helix Font Editor](https://helixfonteditor.netlify.app/) and [Logo Editor](https://joric.github.io/qle/).
@ -259,12 +264,12 @@ void oled_render(void);
void oled_set_cursor(uint8_t col, uint8_t line);
// Advances the cursor to the next page, writing ' ' if true
// Wraps to the begining when out of bounds
// Wraps to the beginning when out of bounds
void oled_advance_page(bool clearPageRemainder);
// Moves the cursor forward 1 character length
// Advance page if there is not enough room for the next character
// Wraps to the begining when out of bounds
// Wraps to the beginning when out of bounds
void oled_advance_char(void);
// Writes a single character to the buffer at current cursor position

View file

@ -0,0 +1,77 @@
# OS Detection
This feature makes a best guess at the host OS based on OS specific behavior during USB setup. It may not always get the correct OS, and shouldn't be relied on as for critical functionality.
Using it you can have OS specific key mappings or combos which work differently on different devices.
It is available for keyboards which use ChibiOS, LUFA and V-USB.
## Usage
In your `rules.mk` add:
```make
OS_DETECTION_ENABLE = yes
```
Include `"os_detection.h"` in your `keymap.c`.
It declares `os_variant_t detected_host_os(void);` which you can call to get detected OS.
It returns one of the following values:
```c
enum {
OS_UNSURE,
OS_LINUX,
OS_WINDOWS,
OS_MACOS,
OS_IOS,
} os_variant_t;
```
?> Note that it takes some time after firmware is booted to detect the OS.
This time is quite short, probably hundreds of milliseconds, but this data may be not ready in keyboard and layout setup functions which run very early during firmware startup.
## Debug
If OS is guessed incorrectly, you may want to collect data about USB setup packets to refine the detection logic.
To do so in your `rules.mk` add:
```make
OS_DETECTION_DEBUG_ENABLE = yes
CONSOLE_ENABLE = yes
```
And also include `"os_detection.h"` in your `keymap.c`.
Then you can define custom keycodes to store data about USB setup packets in EEPROM (persistent memory) and to print it later on host where you can run `qmk console`:
```c
enum custom_keycodes {
STORE_SETUPS = SAFE_RANGE,
PRINT_SETUPS,
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case STORE_SETUPS:
if (record->event.pressed) {
store_setups_in_eeprom();
}
return false;
case PRINT_SETUPS:
if (record->event.pressed) {
print_stored_setups();
}
return false;
}
}
```
Then please open an issue on Github with this information and tell what OS was not detected correctly and if you have any intermediate devices between keyboard and your computer.
## Credits
Original idea is coming from [FingerprintUSBHost](https://github.com/keyboardio/FingerprintUSBHost) project.

View file

@ -22,11 +22,11 @@ POINTING_DEVICE_DRIVER = adns5050
The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.
| Setting | Description | Default |
| ------------------- | ------------------------------------------------------------------- | -------------------------- |
| `ADNS5050_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
| `ADNS5050_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
| `ADNS5050_CS_PIN` | (Required) The pin connected to the cable select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
| Setting | Description | Default |
| ------------------- | ------------------------------------------------------------------ | -------------------------- |
| `ADNS5050_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
| `ADNS5050_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
| `ADNS5050_CS_PIN` | (Required) The pin connected to the Chip Select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
@ -48,7 +48,7 @@ The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surfac
| `ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
| `ADNS9800_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
| `ADNS9800_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
| `ADNS9800_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
| `ADNS9800_CS_PIN` | (Required) Sets the Chip Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
The CPI range is 800-8200, in increments of 200. Defaults to 1800 CPI.
@ -93,20 +93,20 @@ This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the
#### Common settings
| Setting | Description | Default |
| -------------------------------- | ---------------------------------------------------------- | ------------------ |
| `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` |
| `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` |
| `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ |
| `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ |
| Setting | Description | Default |
| -------------------------------- | ---------------------------------------------------------- | ------------------------------------------- |
| `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` |
| `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` |
| `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ |
| `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ |
**`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.
Default attenuation is set to 4X, although if you are using a thicker overlay (such as the curved overlay) you will want a lower attenuation such as 2X. The possible values are:
* `ADC_ATTENUATE_4X`: Least sensitive
* `ADC_ATTENUATE_3X`
* `ADC_ATTENUATE_2X`
* `ADC_ATTENUATE_1X`: Most sensitive
* `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X`: Least sensitive
* `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_3X`
* `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_2X`
* `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_1X`: Most sensitive
**`CIRQUE_PINNACLE_POSITION_MODE`** can be `CIRQUE_PINNACLE_ABSOLUTE_MODE` or `CIRQUE_PINNACLE_RELATIVE_MODE`. Modes differ in supported features/gestures.
@ -124,7 +124,7 @@ Default attenuation is set to 4X, although if you are using a thicker overlay (s
| `CIRQUE_PINNACLE_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
| `CIRQUE_PINNACLE_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `1` |
| `CIRQUE_PINNACLE_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
| `CIRQUE_PINNACLE_SPI_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
| `CIRQUE_PINNACLE_SPI_CS_PIN` | (Required) Sets the Chip Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
Default Scaling is 1024. Actual CPI depends on trackpad diameter.
@ -218,11 +218,14 @@ POINTING_DEVICE_DRIVER = pmw3389
The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.
Both PMW 3360 and PMW 3389 are SPI driven optical sensors, that use a built in IR LED for surface tracking.
If you have different CS wiring on each half you can use `PMW33XX_CS_PIN_RIGHT` or `PMW33XX_CS_PINS_RIGHT` in combination with `PMW33XX_CS_PIN` or `PMW33XX_CS_PINS` to configure both sides independently. If `_RIGHT` values aren't provided, they default to be the same as the left ones.
| Setting | Description | Default |
| ---------------------------- | ------------------------------------------------------------------------------------------- | ------------------------ |
| `PMW33XX_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
| `PMW33XX_CS_PINS` | (Alternative) Sets the Cable Select pins connected to multiple sensors. | _not defined_ |
| `PMW33XX_CS_PIN` | (Required) Sets the Chip Select pin connected to the sensor. | `POINTING_DEVICE_CS_PIN` |
| `PMW33XX_CS_PINS` | (Alternative) Sets the Chip Select pins connected to multiple sensors. | `{PMW33XX_CS_PIN}` |
| `PMW33XX_CS_PIN_RIGHT` | (Optional) Sets the Chip Select pin connected to the sensor on the right half. | `PMW33XX_CS_PIN` |
| `PMW33XX_CS_PINS_RIGHT` | (Optional) Sets the Chip Select pins connected to multiple sensors on the right half. | `{PMW33XX_CS_PIN_RIGHT}` |
| `PMW33XX_CPI` | (Optional) Sets counts per inch sensitivity of the sensor. | _varies_ |
| `PMW33XX_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
| `PMW33XX_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
@ -289,6 +292,7 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
| `POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ |
| `POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ |
| `POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ |
| `POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW` | (Optional) If defined then the motion pin is active-low. | _varies_ |
| `POINTING_DEVICE_TASK_THROTTLE_MS` | (Optional) Limits the frequency that the sensor is polled for motion. | _not defined_ |
| `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE` | (Optional) Enable inertial cursor. Cursor continues moving after a flick gesture and slows down by kinetic friction. | _not defined_ |
| `POINTING_DEVICE_GESTURES_SCROLL_ENABLE` | (Optional) Enable scroll gesture. The gesture that activates the scroll is device dependent. | _not defined_ |
@ -331,10 +335,10 @@ The following configuration options are only available when using `SPLIT_POINTIN
| `pointing_device_handle_buttons(buttons, pressed, button)` | Callback to handle hardware button presses. Returns a `uint8_t`. |
| `pointing_device_get_cpi(void)` | Gets the current CPI/DPI setting from the sensor, if supported. |
| `pointing_device_set_cpi(uint16_t)` | Sets the CPI/DPI, if supported. |
| `pointing_device_get_report(void)` | Returns the current mouse report (as a `mouse_report_t` data structure). |
| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `mouse_report_t` data structured passed to the function. |
| `pointing_device_get_report(void)` | Returns the current mouse report (as a `report_mouse_t` data structure). |
| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `report_mouse_t` data structured passed to the function. |
| `pointing_device_send(void)` | Sends the current mouse report to the host system. Function can be replaced. |
| `has_mouse_report_changed(new_report, old_report)` | Compares the old and new `mouse_report_t` data and returns true only if it has changed. |
| `has_mouse_report_changed(new_report, old_report)` | Compares the old and new `report_mouse_t` data and returns true only if it has changed. |
| `pointing_device_adjust_by_defines(mouse_report)` | Applies rotations and invert configurations to a raw mouse report. |
@ -344,9 +348,9 @@ The combined functions below are only available when using `SPLIT_POINTING_ENABL
| Function | Description |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `pointing_device_set_shared_report(mouse_report)` | Sets the shared mouse report to the assigned `mouse_report_t` data structured passed to the function. |
| `pointing_device_set_cpi_on_side(bool, uint16_t)` | Sets the CPI/DPI of one side, if supported. Passing `true` will set the left and `false` the right` |
| `pointing_device_combine_reports(left_report, right_report)` | Returns a combined mouse_report of left_report and right_report (as a `mouse_report_t` data structure) |
| `pointing_device_set_shared_report(mouse_report)` | Sets the shared mouse report to the assigned `report_mouse_t` data structured passed to the function. |
| `pointing_device_set_cpi_on_side(bool, uint16_t)` | Sets the CPI/DPI of one side, if supported. Passing `true` will set the left and `false` the right |
| `pointing_device_combine_reports(left_report, right_report)` | Returns a combined mouse_report of left_report and right_report (as a `report_mouse_t` data structure) |
| `pointing_device_task_combined_kb(left_report, right_report)` | Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report. |
| `pointing_device_task_combined_user(left_report, right_report)` | Callback, so user code can intercept and modify. Returns a combined mouse report using `pointing_device_combine_reports` |
| `pointing_device_adjust_by_defines_right(mouse_report)` | Applies right side rotations and invert configurations to a raw mouse report. |
@ -487,3 +491,243 @@ report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, re
return pointing_device_combine_reports(left_report, right_report);
}
```
# Troubleshooting
If you are having issues with pointing device drivers debug messages can be enabled that will give you insights in the inner workings. To enable these add to your keyboards `config.h` file:
```c
#define POINTING_DEVICE_DEBUG
```
?> The messages will be printed out to the `CONSOLE` output. For additional information, refer to [Debugging/Troubleshooting QMK](faq_debug.md).
---
# Automatic Mouse Layer :id=pointing-device-auto-mouse
When using a pointing device combined with a keyboard the mouse buttons are often kept on a separate layer from the default keyboard layer, which requires pressing or holding a key to change layers before using the mouse. To make this easier and more efficient an additional pointing device feature may be enabled that will automatically activate a target layer as soon as the pointing device is active _(in motion, mouse button pressed etc.)_ and deactivate the target layer after a set time.
Additionally if any key that is defined as a mouse key is pressed then the layer will be held as long as the key is pressed and the timer will be reset on key release. When a non-mouse key is pressed then the layer is deactivated early _(with some exceptions see below)_. Mod, mod tap, and one shot mod keys are ignored _(i.e. don't hold or activate layer but do not deactivate the layer either)_ when sending a modifier keycode _(e.g. hold for mod tap)_ allowing for mod keys to be used with the mouse without activating the target layer when typing.
All of the standard layer keys (tap toggling, toggle, toggle on, one_shot, layer tap, layer mod) that activate the current target layer are uniquely handled to ensure they behave as expected _(see layer key table below)_. The target layer that can be changed at any point during by calling the `set_auto_mouse_layer(<new_target_layer>);` function.
### Behaviour of Layer keys that activate the target layer
| Layer key as in `keymap.c` | Auto Mouse specific behaviour |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `MO(<target_layer>)` | Treated as a mouse key holding the layer while pressed |
| `LT(<target_layer>)` | When tapped will be treated as non mouse key and mouse key when held |
| `LM(<target_layer>)` | Treated as a mouse key |
| `TG(<target_layer>)` | Will set flag preventing target layer deactivation or removal until pressed again |
| `TO(<target_layer>)` | Same as `TG(<target_layer>)` |
| `TT(<target_layer>)` | Treated as a mouse key when `tap.count < TAPPING_TOGGLE` and as `TG` when `tap.count == TAPPING_TOGGLE` |
| `DF(<target_layer>)` | Skips auto mouse key processing similar to mod keys |
| `OSL(<target_layer>)` | Skips, but if current one shot layer is the target layer then it will prevent target layer deactivation or removal |
## How to enable:
```c
// in config.h:
#define POINTING_DEVICE_AUTO_MOUSE_ENABLE
// only required if not setting mouse layer elsewhere
#define AUTO_MOUSE_DEFAULT_LAYER <index of your mouse layer>
// in keymap.c:
void pointing_device_init_user(void) {
set_auto_mouse_layer(<mouse_layer>); // only required if AUTO_MOUSE_DEFAULT_LAYER is not set to index of <mouse_layer>
set_auto_mouse_enable(true); // always required before the auto mouse feature will work
}
```
Because the auto mouse feature can be disabled/enabled during runtime and starts as disabled by default it must be enabled by calling `set_auto_mouse_enable(true);` somewhere in firmware before the feature will work.
_Note: for setting the target layer during initialization either setting `AUTO_MOUSE_DEFAULT_LAYER` in `config.h` or calling `set_auto_mouse_layer(<mouse_layer>)` can be used._
## How to Customize:
There are a few ways to control the auto mouse feature with both `config.h` options and functions for controlling it during runtime.
### `config.h` Options:
| Define | Description | Range | Units | Default |
| ----------------------------------- | --------------------------------------------------------------------- | :------------------: | :---------: | -------------------------: |
| `POINTING_DEVICE_AUTO_MOUSE_ENABLE` | (Required) Enables auto mouse layer feature | | _None_ | _Not defined_ |
| `AUTO_MOUSE_DEFAULT_LAYER` | (Optional) Index of layer to use as default target layer | 0 - `LAYER_MAX` | _`uint8_t`_ | `1` |
| `AUTO_MOUSE_TIME` | (Optional) Time layer remains active after activation | _ideally_ (250-1000) | _ms_ | `650 ms` |
| `AUTO_MOUSE_DELAY` | (Optional) Lockout time after non-mouse key is pressed | _ideally_ (100-1000) | _ms_ | `TAPPING_TERM` or `200 ms` |
| `AUTO_MOUSE_DEBOUNCE` | (Optional) Time delay from last activation to next update | _ideally_ (10 - 100) | _ms_ | `25 ms` |
### Adding mouse keys
While all default mouse keys and layer keys(for current mouse layer) are treated as mouse keys, additional Keyrecords can be added to mouse keys by adding them to the is_mouse_record_* stack.
#### Callbacks for setting up additional key codes as mouse keys:
| Callback | Description |
| -------------------------------------------------------------------- | -------------------------------------------------- |
| `bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record)` | keyboard level callback for adding mouse keys |
| `bool is_mouse_record_user(uint16_t keycode, keyrecord_t* record)` | user/keymap level callback for adding mouse keys |
##### To use the callback function to add mouse keys:
The following code will cause the enter key and all of the arrow keys to be treated as mouse keys (hold target layer while they are pressed and reset active layer timer).
```c
// in <keyboard>.c:
bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record) {
switch(keycode) {
case KC_ENT:
return true;
case KC_RIGHT ... KC_UP:
return true;
default:
return false;
}
return is_mouse_record_user(keycode, record);
}
```
## Advanced control
There are several functions that allow for more advanced interaction with the auto mouse feature allowing for greater control.
### Functions to control auto mouse enable and target layer:
| Function | Description | Aliases | Return type |
| :--------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------- | --------------: |
| `set_auto_mouse_enable(bool enable)` | Enable or disable auto mouse (true:enable, false:disable) | | `void`(None) |
| `get_auto_mouse_enable(void)` | Return auto mouse enable state (true:enabled, false:disabled) | `AUTO_MOUSE_ENABLED` | `bool` |
| `set_auto_mouse_layer(uint8_t LAYER)` | Change/set the target layer for auto mouse | | `void`(None) |
| `get_auto_mouse_layer(void)` | Return auto mouse target layer index | `AUTO_MOUSE_TARGET_LAYER` | `uint8_t` |
| `remove_auto_mouse_layer(layer_state_t state, bool force)` | Return `state` with target layer removed if appropriate (ignore criteria if `force`) | | `layer_state_t` |
| `auto_mouse_layer_off(void)` | Disable target layer if appropriate will call (makes call to `layer_state_set`) | | `void`(None) |
| `auto_mouse_toggle(void)` | Toggle on/off target toggle state (disables layer deactivation when true) | | `void`(None) |
| `get_auto_mouse_toggle(void)` | Return value of toggling state variable | | `bool` |
_NOTES:_
- _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._
- _It is recommended that `remove_auto_mouse_layer` is used in the `layer_state_set_*` stack of functions and `auto_mouse_layer_off` is used everywhere else_
- _`remove_auto_mouse_layer(state, false)` or `auto_mouse_layer_off()` should be called before any instance of `set_auto_mouse_enabled(false)` or `set_auto_mouse_layer(layer)` to ensure that the target layer will be removed appropriately before disabling auto mouse or changing target to avoid a stuck layer_
### Functions for handling custom key events:
| Function | Description | Return type |
| :--------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------: |
| `auto_mouse_keyevent(bool pressed)` | Auto mouse mouse key event (true: key down, false: key up) | `void`(None) |
| `auto_mouse_trigger_reset(bool pressed)` | Reset auto mouse status on key down and start delay timer (non-mouse key event) | `void`(None) |
| `auto_mouse_toggle(void)` | Toggle on/off target toggle state (disables layer deactivation when true) | `void`(None) |
| `get_auto_mouse_toggle(void)` | Return value of toggling state variable | `bool` |
_NOTE: Generally it would be preferable to use the `is_mouse_record_*` functions to add any additional keys that should act as mouse keys rather than adding `auto_mouse_keyevent(record.event->pressed)` to `process_records_*`_
### Advanced control examples
#### Disable auto mouse on certain layers:
The auto mouse feature can be disabled any time and this can be helpful if you want to disable the auto mouse feature under certain circumstances such as when particular layers are active. One issue however is the handling of the target layer, it needs to be removed appropriately **before** disabling auto mouse _(see notes under control functions above)_. The following function would disable the auto_mouse feature whenever the layers `_LAYER5` through `_LAYER7` are active as the top most layer _(ignoring target layer)_.
```c
// in keymap.c:
layer_state_t layer_state_set_user(layer_state_t state) {
// checks highest layer other than target layer
switch(get_highest_layer(remove_auto_mouse_layer(state, true))) {
case _LAYER5 ... _LAYER7:
// remove_auto_mouse_target must be called to adjust state *before* setting enable
state = remove_auto_mouse_layer(state, false);
set_auto_mouse_enable(false);
break;
default:
set_auto_mouse_enable(true);
break;
}
// recommend that any code that makes adjustment based on auto mouse layer state would go here
return state;
}
```
#### Set different target layer when a particular layer is active:
The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
*NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack* if something similar was to be done in `layer_state_set_user `state = remove_auto_mouse_layer(state, false)` should be used instead
*ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*
```c
// in keymap.c
layer_state_t default_layer_state_set_user(layer_state_t state) {
// switch on change in default layer need to check if target layer already set to avoid turning off layer needlessly
switch(get_highest_layer(state)) {
case _DEFAULT_LAYER_2:
if ((AUTO_MOUSE_TARGET_LAYER) == _MOUSE_LAYER_2) break;
auto_mouse_layer_off();
set_auto_mouse_layer(_MOUSE_LAYER_2);
break;
default:
if((AUTO_MOUSE_TARGET_LAYER) == _MOUSE_LAYER_1) break;
auto_mouse_layer_off();
set_auto_mouse_layer(_MOUSE_LAYER_1);
}
return state;
}
```
### Use custom keys to control auto mouse:
Custom key records could also be created that control the auto mouse feature.
The code example below would create a custom key that would toggle the auto mouse feature on and off when pressed while also setting a bool that could be used to disable other code that may turn it on such as the layer code above.
```c
// in config.h:
enum user_custom_keycodes {
AM_Toggle = SAFE_RANGE
};
// in keymap.c:
// set up global bool to adjust other user code
bool auto_mouse_tg_off = !AUTO_MOUSE_ENABLED;
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
// toggle auto mouse enable key
case AM_Toggle:
if(record->event.pressed) { // key down
auto_mouse_layer_off(); // disable target layer if needed
set_auto_mouse_enabled((AUTO_MOUSE_ENABLED) ^ 1);
auto_mouse_tg_off = !get_auto_mouse_enabled();
} // do nothing on key up
return false; // prevent further processing of keycode
}
}
```
## Customize Target Layer Activation
Layer activation can be customized by overwriting the `auto_mouse_activation` function. This function is checked every time `pointing_device_task` is called when inactive and every `AUTO_MOUSE_DEBOUNCE` ms when active, and will evaluate pointing device level conditions that trigger target layer activation. When it returns true, the target layer will be activated barring the usual exceptions _(e.g. delay time has not expired)_.
By default it will return true if any of the `mouse_report` axes `x`,`y`,`h`,`v` are non zero, or if there is any mouse buttons active in `mouse_report`.
_Note: The Cirque pinnacle track pad already implements a custom activation function that will activate on touchdown as well as movement all of the default conditions, currently this only works for the master side of split keyboards._
| Function | Description | Return type |
| :--------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------: |
| `auto_mouse_activation(report_mouse_t mouse_report)` | Overwritable function that controls target layer activation (when true) | `bool` |
## Auto Mouse for Custom Pointing Device Task
When using a custom pointing device (overwriting `pointing_device_task`) the following code should be somewhere in the `pointing_device_task_*` stack:
```c
void pointing_device_task(void) {
//...Custom pointing device task code
// handle automatic mouse layer (needs report_mouse_t as input)
pointing_device_task_auto_mouse(local_mouse_report);
//...More custom pointing device task code
pointing_device_send();
}
```
In general the following two functions must be implemented in appropriate locations for auto mouse to function:
| Function | Description | Suggested location |
| -------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------: |
| `pointing_device_task_auto_mouse(report_mouse_t mouse_report)` | handles target layer activation and is_active status updates | `pointing_device_task` stack |
| `process_auto_mouse(uint16_t keycode, keyrecord_t* record)` | Keycode processing for auto mouse | `process_record` stack |

View file

@ -1,74 +1,144 @@
## Programmable Button
# Programmable Button :id=programmable-button
Programmable button is a feature that can be used to send keys that have no
predefined meaning.
This means they can be processed on the host side by custom software without
colliding without the operating system trying to interpret these keys.
Programmable Buttons are keys that have no predefined meaning. This means they can be processed on the host side by custom software without the operating system trying to interpret them.
The keycodes are emitted according to the HID usage
"Telephony Device Page" (0x0B), "Programmable button usage" (0x07).
On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#`
keycodes.
(Up to `KEY_MACRO30`)
The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x07`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`).
### Enabling Programmable Button support
?> Currently there is no known support in Windows or macOS. It may be possible to write a custom HID driver to receive these usages, but this is out of the scope of the QMK documentation.
To enable Programmable Button, add the following line to your keymaps `rules.mk`:
## Usage :id=usage
```c
Add the following to your `rules.mk`:
```make
PROGRAMMABLE_BUTTON_ENABLE = yes
```
### Mapping
## Keycodes :id=keycodes
In your keymap you can use the following keycodes to map key presses to Programmable Buttons:
|Key |Aliases|Description |
|---------------------------|-------|----------------------|
|`QK_PROGRAMMABLE_BUTTON_1` |`PB_1` |Programmable button 1 |
|`QK_PROGRAMMABLE_BUTTON_2` |`PB_2` |Programmable button 2 |
|`QK_PROGRAMMABLE_BUTTON_3` |`PB_3` |Programmable button 3 |
|`QK_PROGRAMMABLE_BUTTON_4` |`PB_4` |Programmable button 4 |
|`QK_PROGRAMMABLE_BUTTON_5` |`PB_5` |Programmable button 5 |
|`QK_PROGRAMMABLE_BUTTON_6` |`PB_6` |Programmable button 6 |
|`QK_PROGRAMMABLE_BUTTON_7` |`PB_7` |Programmable button 7 |
|`QK_PROGRAMMABLE_BUTTON_8` |`PB_8` |Programmable button 8 |
|`QK_PROGRAMMABLE_BUTTON_9` |`PB_9` |Programmable button 9 |
|`QK_PROGRAMMABLE_BUTTON_10`|`PB_10`|Programmable button 10|
|`QK_PROGRAMMABLE_BUTTON_11`|`PB_11`|Programmable button 11|
|`QK_PROGRAMMABLE_BUTTON_12`|`PB_12`|Programmable button 12|
|`QK_PROGRAMMABLE_BUTTON_13`|`PB_13`|Programmable button 13|
|`QK_PROGRAMMABLE_BUTTON_14`|`PB_14`|Programmable button 14|
|`QK_PROGRAMMABLE_BUTTON_15`|`PB_15`|Programmable button 15|
|`QK_PROGRAMMABLE_BUTTON_16`|`PB_16`|Programmable button 16|
|`QK_PROGRAMMABLE_BUTTON_17`|`PB_17`|Programmable button 17|
|`QK_PROGRAMMABLE_BUTTON_18`|`PB_18`|Programmable button 18|
|`QK_PROGRAMMABLE_BUTTON_19`|`PB_19`|Programmable button 19|
|`QK_PROGRAMMABLE_BUTTON_20`|`PB_20`|Programmable button 20|
|`QK_PROGRAMMABLE_BUTTON_21`|`PB_21`|Programmable button 21|
|`QK_PROGRAMMABLE_BUTTON_22`|`PB_22`|Programmable button 22|
|`QK_PROGRAMMABLE_BUTTON_23`|`PB_23`|Programmable button 23|
|`QK_PROGRAMMABLE_BUTTON_24`|`PB_24`|Programmable button 24|
|`QK_PROGRAMMABLE_BUTTON_25`|`PB_25`|Programmable button 25|
|`QK_PROGRAMMABLE_BUTTON_26`|`PB_26`|Programmable button 26|
|`QK_PROGRAMMABLE_BUTTON_27`|`PB_27`|Programmable button 27|
|`QK_PROGRAMMABLE_BUTTON_28`|`PB_28`|Programmable button 28|
|`QK_PROGRAMMABLE_BUTTON_29`|`PB_29`|Programmable button 29|
|`QK_PROGRAMMABLE_BUTTON_30`|`PB_30`|Programmable button 30|
|`QK_PROGRAMMABLE_BUTTON_31`|`PB_31`|Programmable button 31|
|`QK_PROGRAMMABLE_BUTTON_32`|`PB_32`|Programmable button 32|
|Key |Description |
|------------------------|----------------------|
|`PROGRAMMABLE_BUTTON_1` |Programmable button 1 |
|`PROGRAMMABLE_BUTTON_2` |Programmable button 2 |
|`PROGRAMMABLE_BUTTON_3` |Programmable button 3 |
|`PROGRAMMABLE_BUTTON_4` |Programmable button 4 |
|`PROGRAMMABLE_BUTTON_5` |Programmable button 5 |
|`PROGRAMMABLE_BUTTON_6` |Programmable button 6 |
|`PROGRAMMABLE_BUTTON_7` |Programmable button 7 |
|`PROGRAMMABLE_BUTTON_8` |Programmable button 8 |
|`PROGRAMMABLE_BUTTON_9` |Programmable button 9 |
|`PROGRAMMABLE_BUTTON_10`|Programmable button 10|
|`PROGRAMMABLE_BUTTON_11`|Programmable button 11|
|`PROGRAMMABLE_BUTTON_12`|Programmable button 12|
|`PROGRAMMABLE_BUTTON_13`|Programmable button 13|
|`PROGRAMMABLE_BUTTON_14`|Programmable button 14|
|`PROGRAMMABLE_BUTTON_15`|Programmable button 15|
|`PROGRAMMABLE_BUTTON_16`|Programmable button 16|
|`PROGRAMMABLE_BUTTON_17`|Programmable button 17|
|`PROGRAMMABLE_BUTTON_18`|Programmable button 18|
|`PROGRAMMABLE_BUTTON_19`|Programmable button 19|
|`PROGRAMMABLE_BUTTON_20`|Programmable button 20|
|`PROGRAMMABLE_BUTTON_21`|Programmable button 21|
|`PROGRAMMABLE_BUTTON_22`|Programmable button 22|
|`PROGRAMMABLE_BUTTON_23`|Programmable button 23|
|`PROGRAMMABLE_BUTTON_24`|Programmable button 24|
|`PROGRAMMABLE_BUTTON_25`|Programmable button 25|
|`PROGRAMMABLE_BUTTON_26`|Programmable button 26|
|`PROGRAMMABLE_BUTTON_27`|Programmable button 27|
|`PROGRAMMABLE_BUTTON_28`|Programmable button 28|
|`PROGRAMMABLE_BUTTON_29`|Programmable button 29|
|`PROGRAMMABLE_BUTTON_30`|Programmable button 30|
|`PROGRAMMABLE_BUTTON_31`|Programmable button 31|
|`PROGRAMMABLE_BUTTON_32`|Programmable button 32|
|`PB_1` to `PB_32` |Aliases for keymaps |
## API :id=api
### API
### `void programmable_button_clear(void)` :id=api-programmable-button-clear
You can also use a dedicated API defined in `programmable_button.h` to interact with this feature:
Clear the programmable button report.
```
void programmable_button_clear(void);
void programmable_button_send(void);
void programmable_button_on(uint8_t code);
void programmable_button_off(uint8_t code);
bool programmable_button_is_on(uint8_t code);
uint32_t programmable_button_get_report(void);
void programmable_button_set_report(uint32_t report);
```
---
### `void programmable_button_add(uint8_t index)` :id=api-programmable-button-add
Set the state of a button.
#### Arguments :id=api-programmable-button-add-arguments
- `uint8_t index`
The index of the button to press, from 0 to 31.
---
### `void programmable_button_remove(uint8_t index)` :id=api-programmable-button-remove
Reset the state of a button.
#### Arguments :id=api-programmable-button-remove-arguments
- `uint8_t index`
The index of the button to release, from 0 to 31.
---
### `void programmable_button_register(uint8_t index)` :id=api-programmable-button-register
Set the state of a button, and flush the report.
#### Arguments :id=api-programmable-button-register-arguments
- `uint8_t index`
The index of the button to press, from 0 to 31.
---
### `void programmable_button_unregister(uint8_t index)` :id=api-programmable-button-unregister
Reset the state of a button, and flush the report.
#### Arguments :id=api-programmable-button-unregister-arguments
- `uint8_t index`
The index of the button to release, from 0 to 31.
---
### `bool programmable_button_is_on(uint8_t index)` :id=api-programmable-button-is-on
Get the state of a button.
#### Arguments :id=api-programmable-button-is-on-arguments
- `uint8_t index`
The index of the button to check, from 0 to 31.
#### Return Value :id=api-programmable-button-is-on-return
`true` if the button is pressed.
---
### `void programmable_button_flush(void)` :id=api-programmable-button-flush
Send the programmable button report to the host.
---
### `uint32_t programmable_button_get_report(void)` :id=api-programmable-button-get-report
Get the programmable button report.
#### Return Value :id=api-programmable-button-get-report-return
The bitmask of programmable button states.
---
### `void programmable_button_set_report(uint32_t report)` :id=api-programmable-button-set-report
Set the programmable button report.
#### Arguments :id=api-programmable-button-set-report-arguments
- `uint32_t report`
A bitmask of programmable button states.

View file

@ -32,13 +32,14 @@ In rules.mk:
```make
PS2_MOUSE_ENABLE = yes
PS2_USE_BUSYWAIT = yes
PS2_ENABLE = yes
PS2_DRIVER = busywait
```
In your keyboard config.h:
```c
#ifdef PS2_USE_BUSYWAIT
#ifdef PS2_DRIVER_BUSYWAIT
# define PS2_CLOCK_PIN D1
# define PS2_DATA_PIN D2
#endif
@ -52,13 +53,14 @@ In rules.mk:
```make
PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes
PS2_ENABLE = yes
PS2_DRIVER = interrupt
```
In your keyboard config.h:
```c
#ifdef PS2_USE_INT
#ifdef PS2_DRIVER_INTERRUPT
#define PS2_CLOCK_PIN D2
#define PS2_DATA_PIN D5
@ -84,7 +86,8 @@ In rules.mk:
```
PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes
PS2_ENABLE = yes
PS2_DRIVER = interrupt
```
In your keyboard config.h:
@ -108,13 +111,14 @@ In rules.mk:
```make
PS2_MOUSE_ENABLE = yes
PS2_USE_USART = yes
PS2_ENABLE = yes
PS2_DRIVER = usart
```
In your keyboard config.h:
```c
#ifdef PS2_USE_USART
#ifdef PS2_DRIVER_USART
#define PS2_CLOCK_PIN D5
#define PS2_DATA_PIN D2

View file

@ -23,7 +23,7 @@ You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_<N>` de
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
@ -45,17 +45,17 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 25
#define DRIVER_2_LED_TOTAL 24
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
For split keyboards using `RGB_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@ -90,7 +90,7 @@ You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` de
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
@ -131,17 +131,17 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 58
#define DRIVER_2_LED_TOTAL 10
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Currently only 4 drivers are supported, but it would be trivial to support all 8 combinations.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@ -164,7 +164,7 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3737
```
You can use between 1 and 2 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_2` define for second IC if not present on your keyboard.
You can use between 1 and 4 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard.
Configure the hardware via your `config.h`:
@ -177,9 +177,11 @@ Configure the hardware via your `config.h`:
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
The IS31FL3737 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
@ -212,16 +214,16 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 36
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@ -233,7 +235,7 @@ const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
}
```
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1` for now).
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1`, `2`, or `3` for now).
---
### IS31FLCOMMON :id=is31flcommon
@ -250,7 +252,7 @@ Where `<driver name>` is the applicable LED driver chip as below
| Driver Name | Data Sheet | Capability |
|-------------|------------|------------|
| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 60 RGB, 30x6 Matrix |
| `ISSIFL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 66 RGB, 18x11 Matrix |
| `IS31FL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 66 RGB, 18x11 Matrix |
| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 48 RGB, 18x8 Matrix |
| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 24 RGB, 18x4 Matrix |
@ -263,14 +265,14 @@ Configure the hardware via your `config.h`:
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first RGB driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional RGB drivers | |
| `ISSI_SSR_<N>` | (Optional) Configuration for the Spread Spectrum Register | |
| `ISSI_CONFIGURATION` | (Optional) Configuration for the Configuration Register | |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_PULLDOWNUP` | (Optional) Configuration for the Pull Up & Pull Down Register | |
| `ISSI_TEMP` | (Optional) Configuration for the Tempature Register | |
| `ISSI_TEMP` | (Optional) Configuration for the Temperature Register | |
| `ISSI_PWM_ENABLE` | (Optional) Configuration for the PWM Enable Register | |
| `ISSI_PWM_SET` | (Optional) Configuration for the PWM Setting Register | |
| `ISSI_SCAL_RED` | (Optional) Configuration for the RED LEDs in Scaling Registers | 0xFF |
@ -300,17 +302,17 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
const is31_led __flash g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@ -361,7 +363,7 @@ Configure the hardware via your `config.h`:
// The pin connected to the data pin of the LEDs
#define RGB_DI_PIN D7
// The number of LEDs connected
#define DRIVER_LED_TOTAL 70
#define RGB_MATRIX_LED_COUNT 70
```
?> There are additional configuration options for ARM controllers that offer increased performance over the default bitbang driver. Please see [WS2812 Driver](ws2812_driver.md) for more information.
@ -385,7 +387,7 @@ Configure the hardware via your `config.h`:
// The pin connected to the clock pin of the LEDs
#define RGB_CI_PIN D6
// The number of LEDs connected
#define DRIVER_LED_TOTAL 70
#define RGB_MATRIX_LED_COUNT 70
```
---
@ -408,7 +410,7 @@ You can use up to 2 AW20216 IC's. Do not specify `DRIVER_<N>_xxx` defines for IC
| `DRIVER_1_LED_TOTAL` | (Required) How many RGB lights are connected to first RGB driver | |
| `DRIVER_2_LED_TOTAL` | (Optional) How many RGB lights are connected to second RGB driver | |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `AW_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
| `AW_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
| `AW_SPI_MODE` | (Optional) Mode for SPI communication (0-3, defines polarity and phase of the clock) | 3 |
@ -426,15 +428,15 @@ Here is an example using 2 drivers.
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 32
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const aw_led PROGMEM g_aw_leds[DRIVER_LED_TOTAL] = {
const aw_led PROGMEM g_aw_leds[RGB_MATRIX_LED_COUNT] = {
/* Each AW20216 channel is controlled by a register at some offset between 0x00
* and 0xD7 inclusive.
* See drivers/awinic/aw20216.h for the mapping between register offsets and
@ -560,7 +562,7 @@ enum rgb_matrix_effects {
RGB_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom
RGB_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in
RGB_MATRIX_CYCLE_OUT_IN_DUAL, // Full dual gradients scrolling out to in
RGB_MATRIX_RAINBOW_MOVING_CHEVRON, // Full gradent Chevron shapped scrolling left to right
RGB_MATRIX_RAINBOW_MOVING_CHEVRON, // Full gradient Chevron shapped scrolling left to right
RGB_MATRIX_CYCLE_PINWHEEL, // Full gradient spinning pinwheel around center of keyboard
RGB_MATRIX_CYCLE_SPIRAL, // Full gradient spinning spiral around center of keyboard
RGB_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard
@ -574,7 +576,7 @@ enum rgb_matrix_effects {
RGB_MATRIX_PIXEL_FRACTAL, // Single hue fractal filled keys pulsing horizontally out to edges
RGB_MATRIX_PIXEL_FLOW, // Pulsing RGB flow along LED wiring with random hues
RGB_MATRIX_PIXEL_RAIN, // Randomly light keys with random hues
#if define(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
RGB_MATRIX_TYPING_HEATMAP, // How hot is your WPM!
RGB_MATRIX_DIGITAL_RAIN, // That famous computer simulation
#endif
@ -791,17 +793,16 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS // enable framebuffer effects
#define RGB_DISABLE_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
#define RGB_DISABLE_AFTER_TIMEOUT 0 // OBSOLETE: number of ticks to wait until disabling effects
#define RGB_MATRIX_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
#define RGB_MATRIX_LED_PROCESS_LIMIT (RGB_MATRIX_LED_COUNT + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT // Sets the default mode, if none has been set
#define RGB_MATRIX_STARTUP_HUE 0 // Sets the default hue value, if none has been set
#define RGB_MATRIX_STARTUP_SAT 255 // Sets the default saturation value, if none has been set
#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define RGB_MATRIX_STARTUP_SPD 127 // Sets the default animation speed, if none has been set
#define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT // Sets the default mode, if none has been set
#define RGB_MATRIX_DEFAULT_HUE 0 // Sets the default hue value, if none has been set
#define RGB_MATRIX_DEFAULT_SAT 255 // Sets the default saturation value, if none has been set
#define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
#define RGB_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set
#define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature)
#define RGB_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
// If RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR
@ -824,7 +825,7 @@ Where `28` is an unused index from `eeconfig.h`.
|Function |Description |
|--------------------------------------------|-------------|
|`rgb_matrix_set_color_all(r, g, b)` |Set all of the LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|`rgb_matrix_set_color(index, r, g, b)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255, and `index` is between 0 and `DRIVER_LED_TOTAL` (not written to EEPROM) |
|`rgb_matrix_set_color(index, r, g, b)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255, and `index` is between 0 and `RGB_MATRIX_LED_COUNT` (not written to EEPROM) |
### Disable/Enable Effects :id=disable-enable-effects
|Function |Description |
@ -889,16 +890,21 @@ Where `28` is an unused index from `eeconfig.h`.
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `rgb_matrix_indicators_kb` or `rgb_matrix_indicators_user` function for that:
```c
void rgb_matrix_indicators_kb(void) {
bool rgb_matrix_indicators_kb(void) {
if (!rgb_matrix_indicators_user()) {
return false;
}
rgb_matrix_set_color(index, red, green, blue);
return true;
}
```
In addition, there are the advanced indicator functions. These are aimed at those with heavily customized displays, where rendering every LED per cycle is expensive. Such as some of the "drashna" layouts. This includes a special macro to help make this easier to use: `RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b)`.
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
RGB_MATRIX_INDICATOR_SET_COLOR(index, red, green, blue);
return false;
}
```
@ -906,21 +912,22 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
Caps Lock indicator on alphanumeric flagged keys:
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
if (host_keyboard_led_state().caps_lock) {
for (uint8_t i = led_min; i <= led_max; i++) {
for (uint8_t i = led_min; i < led_max; i++) {
if (g_led_config.flags[i] & LED_FLAG_KEYLIGHT) {
rgb_matrix_set_color(i, RGB_RED);
}
}
}
return false;
}
```
Layer indicator on all keys:
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
for (uint8_t i = led_min; i <= led_max; i++) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
for (uint8_t i = led_min; i < led_max; i++) {
switch(get_highest_layer(layer_state|default_layer_state)) {
case 2:
rgb_matrix_set_color(i, RGB_BLUE);
@ -932,12 +939,13 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
break;
}
}
return false;
}
```
Layer indicator only on keys with configured keycodes:
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
if (get_highest_layer(layer_state) > 0) {
uint8_t layer = get_highest_layer(layer_state);
@ -945,13 +953,14 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
uint8_t index = g_led_config.matrix_co[row][col];
if (index >= led_min && index <= led_max && index != NO_LED &&
if (index >= led_min && index < led_max && index != NO_LED &&
keymap_key_to_keycode(layer, (keypos_t){col,row}) > KC_TRNS) {
rgb_matrix_set_color(index, RGB_GREEN);
}
}
}
}
return false;
}
```
@ -962,7 +971,7 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
This example sets the modifiers to be a specific color based on the layer state. You can use a switch case here, instead, if you would like. This uses HSV and then converts to RGB, because this allows the brightness to be limited (important when using the WS2812 driver).
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
HSV hsv = {0, 255, 255};
if (layer_state_is(layer_state, 2)) {
@ -976,27 +985,29 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
}
RGB rgb = hsv_to_rgb(hsv);
for (uint8_t i = led_min; i <= led_max; i++) {
for (uint8_t i = led_min; i < led_max; i++) {
if (HAS_FLAGS(g_led_config.flags[i], 0x01)) { // 0x01 == LED_FLAG_MODIFIER
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
}
return false;
}
```
If you want to indicate a Host LED status (caps lock, num lock, etc), you can use something like this to light up the caps lock key:
```c
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
if (host_keyboard_led_state().caps_lock) {
RGB_MATRIX_INDICATOR_SET_COLOR(5, 255, 255, 255); // assuming caps lock is at led #5
} else {
RGB_MATRIX_INDICATOR_SET_COLOR(5, 0, 0, 0);
}
return false;
}
```
!> RGB indicators on split keyboards will require state information synced to the slave half (e.g. `#define SPLIT_LAYER_STATE_ENABLE`). See [data sync options](feature_split_keyboard.md#data-sync-options) for more details.
?> RGB indicators on split keyboards will require state information synced to the slave half (e.g. `#define SPLIT_LAYER_STATE_ENABLE`). See [data sync options](feature_split_keyboard.md#data-sync-options) for more details.
#### Indicators without RGB Matrix Effect

View file

@ -165,7 +165,7 @@ The following options are used to tweak the various animations:
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
### Example Usage to Reduce Memory Footprint
1. Selectively disable the animations you want to enable. The following would enable two animations and save about 4KiB:
1. Use `#undef` to selectively disable animations. The following would disable two animations and save about 4KiB:
```diff
#undef RGBLED_NUM
@ -302,7 +302,7 @@ void keyboard_post_init_user(void) {
// after the flag has been flipped...
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case DEBUG:
case QK_DEBUG_TOGGLE:
rgblight_blink_layer(debug_enable ? 0 : 1, 500);
break;
@ -319,13 +319,13 @@ You can also use `rgblight_blink_layer_repeat` to specify the amount of times th
```c
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case DEBUG:
case QK_DEBUG_TOGGLE:
rgblight_blink_layer_repeat(debug_enable ? 0 : 1, 200, 3);
break;
}
}
```
would turn the layer 0 (or 1) on and off again three times when `DEBUG` is pressed.
would turn the layer 0 (or 1) on and off again three times when `DB_TOGG` is pressed.
Blinking accumulates layers so if multiple layers are set blinking at the same time they will all blink for the duration and repeat times of the last layer to be blinked.
To stop these other layers from blinking use `rgblight_unblink_layer` or `rgblight_unblink_all_but_layer`:

View file

@ -26,12 +26,12 @@ SECURE_ENABLE = yes
## Keycodes
| Key | Description |
|------------------|--------------------------------------------------------------------------------|
| `SECURE_LOCK` | Revert back to a locked state |
| `SECURE_UNLOCK` | Forces unlock without performing a unlock sequence |
| `SECURE_TOGGLE` | Toggle directly between locked and unlock without performing a unlock sequence |
| `SECURE_REQUEST` | Request that user perform the unlock sequence |
| Key |Aliases | Description |
|---------------------|---------|--------------------------------------------------------------------------------|
| `QK_SECURE_LOCK` |`SE_LOCK`| Revert back to a locked state |
| `QK_SECURE_UNLOCK` |`SE_UNLK`| Forces unlock without performing a unlock sequence |
| `QK_SECURE_TOGGLE` |`SE_TOGG`| Toggle directly between locked and unlock without performing a unlock sequence |
| `QK_SECURE_REQUEST` |`SE_REQ` | Request that user perform the unlock sequence |
## Configuration

View file

@ -40,20 +40,20 @@ While the tempo defines the absolute speed at which the sequencer goes through t
## Keycodes
|Keycode |Description |
|------- |----------- |
|`SQ_ON` |Start the step sequencer |
|`SQ_OFF` |Stop the step sequencer |
|`SQ_TOG` |Toggle the step sequencer playback |
|`SQ_SALL`|Enable all the steps |
|`SQ_SCLR`|Disable all the steps |
|`SQ_S(n)`|Toggle the step `n` |
|`SQ_TMPD`|Decrease the tempo |
|`SQ_TMPU`|Increase the tempo |
|`SQ_R(n)`|Set the resolution to n |
|`SQ_RESD`|Change to the slower resolution |
|`SQ_RESU`|Change to the faster resolution |
|`SQ_T(n)`|Set `n` as the only active track or deactivate all |
|Key |Aliases |Description |
|-------------------------------|---------|---------------------------------------------------|
|`QK_SEQUENCER_ON` |`SQ_ON` |Start the step sequencer |
|`QK_SEQUENCER_OFF` |`SQ_OFF` |Stop the step sequencer |
|`QK_SEQUENCER_TOGGLE` |`SQ_TOG` |Toggle the step sequencer playback |
|`QK_SEQUENCER_STEPS_ALL` |`SQ_SALL`|Enable all the steps |
|`QK_SEQUENCER_STEPS_CLEAR` |`SQ_SCLR`|Disable all the steps |
|`QK_SEQUENCER_TEMPO_DOWN` |`SQ_TMPD`|Decrease the tempo |
|`QK_SEQUENCER_TEMPO_UP` |`SQ_TMPU`|Increase the tempo |
|`QK_SEQUENCER_RESOLUTION_DOWN` |`SQ_RESD`|Change to the slower resolution |
|`QK_SEQUENCER_RESOLUTION_UP` |`SQ_RESU`|Change to the faster resolution |
|`SQ_S(n)` | |Toggle the step `n` |
|`SQ_R(n)` | |Set the resolution to n |
|`SQ_T(n)` | |Set `n` as the only active track or deactivate all |
## Functions

View file

@ -5,22 +5,22 @@ Steve Losh described the [Space Cadet Shift](https://stevelosh.com/blog/2012/10/
## Usage
Firstly, in your keymap, do one of the following:
- Replace the Left Shift key with `KC_LSPO` (Left Shift, Parenthesis Open), and Right Shift with `KC_RSPC` (Right Shift, Parenthesis Close).
- Replace the Left Control key with `KC_LCPO` (Left Control, Parenthesis Open), and Right Control with `KC_RCPC` (Right Control, Parenthesis Close).
- Replace the Left Alt key with `KC_LAPO` (Left Alt, Parenthesis Open), and Right Alt with `KC_RAPC` (Right Alt, Parenthesis Close).
- Replace any Shift key in your keymap with `KC_SFTENT` (Right Shift, Enter).
- Replace the Left Shift key with `SC_LSPO` (Left Shift, Parenthesis Open), and Right Shift with `SC_RSPC` (Right Shift, Parenthesis Close).
- Replace the Left Control key with `SC_LCPO` (Left Control, Parenthesis Open), and Right Control with `SC_RCPC` (Right Control, Parenthesis Close).
- Replace the Left Alt key with `SC_LAPO` (Left Alt, Parenthesis Open), and Right Alt with `SC_RAPC` (Right Alt, Parenthesis Close).
- Replace any Shift key in your keymap with `SC_SENT` (Right Shift, Enter).
## Keycodes
|Keycode |Description |
|-----------|-------------------------------------------|
|`KC_LSPO` |Left Shift when held, `(` when tapped |
|`KC_RSPC` |Right Shift when held, `)` when tapped |
|`KC_LCPO` |Left Control when held, `(` when tapped |
|`KC_RCPC` |Right Control when held, `)` when tapped |
|`KC_LAPO` |Left Alt when held, `(` when tapped |
|`KC_RAPC` |Right Alt when held, `)` when tapped |
|`KC_SFTENT`|Right Shift when held, Enter when tapped |
|Keycode |Aliases |Description |
|----------------------------------------------|---------|----------------------------------------|
|`QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN` |`SC_LCPO`|Left Control when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE` |`SC_RCPC`|Right Control when held, `)` when tapped|
|`QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN` |`SC_LSPO`|Left Shift when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE`|`SC_RSPC`|Right Shift when held, `)` when tapped |
|`QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN` |`SC_LAPO`|Left Alt when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE` |`SC_RAPC`|Right Alt when held, `)` when tapped |
|`QK_SPACE_CADET_RIGHT_SHIFT_ENTER` |`SC_SENT`|Right Shift when held, Enter when tapped|
## Caveats
@ -32,7 +32,7 @@ COMMAND_ENABLE = no
## Configuration
By default Space Cadet assumes a US ANSI layout, but if your layout uses different keys for parentheses, you can redefine them in your `config.h`. In addition, you can redefine the modifier to send on tap, or even send no modifier at all. The new configuration defines bundle all options up into a single define of 3 key codes in this order: the `Modifier` when held or when used with other keys, the `Tap Modifer` sent when tapped (no modifier if `KC_TRNS`), finally the `Keycode` sent when tapped. Now keep in mind, mods from other keys will still apply to the `Keycode` if say `KC_RSFT` is held while tapping `KC_LSPO` key with `KC_TRNS` as the `Tap Modifer`.
By default Space Cadet assumes a US ANSI layout, but if your layout uses different keys for parentheses, you can redefine them in your `config.h`. In addition, you can redefine the modifier to send on tap, or even send no modifier at all. The new configuration defines bundle all options up into a single define of 3 key codes in this order: the `Modifier` when held or when used with other keys, the `Tap Modifer` sent when tapped (no modifier if `KC_TRNS`), finally the `Keycode` sent when tapped. Now keep in mind, mods from other keys will still apply to the `Keycode` if say `KC_RSFT` is held while tapping `SC_LSPO` key with `KC_TRNS` as the `Tap Modifer`.
|Define |Default |Description |
|----------------|-------------------------------|---------------------------------------------------------------------------------|
@ -48,7 +48,7 @@ By default Space Cadet assumes a US ANSI layout, but if your layout uses differe
## Obsolete Configuration
These defines are used in the above defines internally to support backwards compatibility, so you may continue to use them, however the above defines open up a larger range of flexibility than before. As an example, say you want to not send any modifier when you tap just `KC_LSPO`, with the old defines you had an all or nothing choice of using the `DISABLE_SPACE_CADET_MODIFIER` define. Now you can define that key as: `#define LSPO_KEYS KC_LSFT, KC_TRNS, KC_9`. This tells the system to set Left Shift if held or used with other keys, then on tap send no modifier (transparent) with the `KC_9`.
These defines are used in the above defines internally to support backwards compatibility, so you may continue to use them, however the above defines open up a larger range of flexibility than before. As an example, say you want to not send any modifier when you tap just `SC_LSPO`, with the old defines you had an all or nothing choice of using the `DISABLE_SPACE_CADET_MODIFIER` define. Now you can define that key as: `#define LSPO_KEYS KC_LSFT, KC_TRNS, KC_9`. This tells the system to set Left Shift if held or used with other keys, then on tap send no modifier (transparent) with the `KC_9`.
|Define |Default |Description |
|------------------------------|-------------|------------------------------------------------------------------|

View file

@ -79,6 +79,16 @@ If you're using a custom transport (communication method), then you will also ne
SPLIT_TRANSPORT = custom
```
### Layout Macro
Configuring your layout in a split keyboard works slightly differently to a non-split keyboard. Take for example the following layout. The top left numbers refer to the matrix row and column, and the bottom right are the order of the keys in the layout:
![Physical layout](https://i.imgur.com/QeY6kMQ.png)
Since the matrix scanning procedure operates on entire rows, it first populates the left half's rows, then the right half's. Thus, the matrix as QMK views it has double the rows instead of double the columns:
![Matrix](https://i.imgur.com/4wjJzBU.png)
### Setting Handedness
By default, the firmware does not know which side is which; it needs some help to determine that. There are several ways to do this, listed in order of precedence.
@ -132,50 +142,48 @@ To enable this method, add the following to your `config.h` file:
#define EE_HANDS
```
Next, you will have to flash the EEPROM files once for the correct hand to the controller on each halve. You can do this manually with the following bootloader targets while flashing the firmware:
Next, you will have to flash the correct handedness option to the controller on each halve. You can do this manually with the following bootloader targets using `qmk flash -kb <keyboard> -km <keymap> -bl <bootloader>` command to flash:
* AVR controllers with the Caterina bootloader (e.g. Pro Micro):
* `:avrdude-split-left`
* `:avrdude-split-right`
* AVR controllers with the stock Amtel DFU or DFU compatible bootloader (e.g. Elite-C):
* `:dfu-split-left`
* `:dfu-split-right`
* ARM controllers with a DFU compatible bootloader (e.g. Proton-C):
* `:dfu-util-split-left`
* `:dfu-util-split-right`
* ARM controllers with a UF2 compatible bootloader:
* `:uf2-split-left`
* `:uf2-split-right`
Example:
|Microcontroller Type|Bootloader Parameter|
|--------------------|--------------------|
|AVR controllers with Caterina bootloader<br>(e.g. Pro Micro)|`avrdude-split-left`<br>`avrdude-split-right`|
|AVR controllers with the stock Amtel DFU or DFU compatible bootloader<br>(e.g. Elite-C)|`dfu-split-left`<br>`dfu-split-right`|
|ARM controllers with a DFU compatible bootloader<br>(e.g. Proton-C)|`dfu-util-split-left`<br>`dfu-util-split-right`|
|ARM controllers with a UF2 compatible bootloader<br>(e.g. RP2040)|`uf2-split-left`<br>`uf2-split-right`|
Example for `crkbd/rev1` keyboard with normal AVR Pro Micro MCUs, reset the left controller and run:
```
make crkbd:default:avrdude-split-left
qmk flash -kb crkbd/rev1 -km default -bl avrdude-split-left
```
Reset the right controller and run:
```
qmk flash -kb crkbd/rev1 -km default -bl avrdude-split-right
```
?> ARM controllers using `dfu-util` will require an EEPROM reset after setting handedness. This can be done using the `EEP_RST` keycode or [Bootmagic Lite](feature_bootmagic.md). Controllers using emulated EEPROM will always require handedness parameter when flashing the firmware.
?> Some controllers (e.g. Blackpill with DFU compatible bootloader) will need to be flashed with handedness bootloader parameter every time because it is not retained between flashes.
?> [QMK Toolbox]() can also be used to flash EEPROM handedness files. Place the controller in bootloader mode and select menu option Tools -> EEPROM -> Set Left/Right Hand
This setting is not changed when re-initializing the EEPROM using the `EEP_RST` key, or using the `eeconfig_init()` function. However, if you reset the EEPROM outside of the firmware's built in options (such as flashing a file that overwrites the `EEPROM`, like how the [QMK Toolbox]()'s "Reset EEPROM" button works), you'll need to re-flash the controller with the `EEPROM` files.
This setting is not changed when re-initializing the EEPROM using the `EE_CLR` key, or using the `eeconfig_init()` function. However, if you reset the EEPROM outside of the firmware's built in options (such as flashing a file that overwrites the `EEPROM`, like how the [QMK Toolbox]()'s "Reset EEPROM" button works), you'll need to re-flash the controller with the `EEPROM` files.
You can find the `EEPROM` files in the QMK firmware repo, [here](https://github.com/qmk/qmk_firmware/tree/master/quantum/split_common).
#### Handedness by `#define`
You can set the handedness at compile time. This is done by adding the following to your `config.h` file:
You can use this option when USB cable is always connected to just one side of the split keyboard.
If the USB cable is always connected to the right side, add the following to your `config.h` file and flash both sides with this option:
```c
#define MASTER_RIGHT
```
or
If the USB cable is always connected to the left side, add the following to your `config.h` file and flash both sides with this option:
```c
#define MASTER_LEFT
```
If neither are defined, the handedness defaults to `MASTER_LEFT`.
?> If neither options are defined, the handedness defaults to `MASTER_LEFT`.
### Communication Options
@ -286,6 +294,12 @@ This enables transmitting the pointing device status to the master side of the s
!> There is additional required configuration for `SPLIT_POINTING_ENABLE` outlined in the [pointing device documentation](feature_pointing_device.md?id=split-keyboard-configuration).
```c
#define SPLIT_HAPTIC_ENABLE
```
This enables triggering of haptic feedback on the slave side of the split keyboard. For DRV2605L this will send the mode, but for solenoids it is expected that the desired mode is already set up on the slave.
### Custom data sync between sides :id=custom-data-sync
QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
@ -422,6 +436,17 @@ This sets the maximum timeout when detecting master/slave when using `SPLIT_USB_
```
This sets the poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
```c
#define SPLIT_WATCHDOG_ENABLE
```
This will enable a software watchdog on any side delegated as slave and will reboot the keyboard if no successful communication occurs within `SPLIT_WATCHDOG_TIMEOUT`. This can be particularly helpful when `SPLIT_USB_DETECT` delegates both sides as slave in some circumstances.
```c
#define SPLIT_WATCHDOG_TIMEOUT 3000
```
This set the maximum slave timeout when waiting for communication from master when using `SPLIT_WATCHDOG_ENABLE`
## Hardware Considerations and Mods
Master/slave delegation is made either by detecting voltage on VBUS connection or waiting for USB communication (`SPLIT_USB_DETECT`). Pro Micro boards can use VBUS detection out of the box and be used with or without `SPLIT_USB_DETECT`.

View file

@ -19,18 +19,18 @@ Note that the array indices are reversed same as the matrix and the values are o
## Swap Keycodes
|Key |Description |
|-----------|-------------------------------------------------------------------------|
|`SH_T(key)`|Sends `key` with a tap; momentary swap when held. |
|`SH_ON` |Turns on swapping and leaves it on. |
|`SH_OFF` |Turn off swapping and leaves it off. Good for returning to a known state.|
|`SH_MON` |Swaps hands when pressed, returns to normal when released (momentary). |
|`SH_MOFF` |Momentarily turns off swap. |
|`SH_TG` |Toggles swap on and off with every key press. |
|`SH_TT` |Momentary swap when held, toggles with repeated taps (see below). |
|`SH_OS` |One shot swap hands: toggles while pressed or until next key press. |
|Key |Aliases |Description |
|-----------------------------|---------|----------------------------------------------------|
|`SH_T(kc)` | |Momentary swap when held, `kc` when tapped |
|`QK_SWAP_HANDS_ON` |`SH_ON` |Turn on hand swap |
|`QK_SWAP_HANDS_OFF` |`SH_OFF` |Turn off hand swap |
|`QK_SWAP_HANDS_MOMENTARY_ON` |`SH_MON` |Turn on hand swap while held |
|`QK_SWAP_HANDS_MOMENTARY_OFF`|`SH_MOFF`|Turn off hand swap while held |
|`QK_SWAP_HANDS_TOGGLE` |`SH_TOGG`|Toggle hand swap |
|`QK_SWAP_HANDS_TAP_TOGGLE` |`SH_TT` |Momentary swap when held, toggle when tapped |
|`QK_SWAP_HANDS_ONE_SHOT` |`SH_OS` |Turn on hand swap while held or until next key press|
`SH_TT` swap-hands tap-toggle key is similar to [layer tap-toggle](feature_layers.md?id=switching-and-toggling-layers). Tapping repeatedly (5 taps by default) will toggle swap-hands on or off, like `SH_TG`. Tap-toggle count can be changed by defining a value for `TAPPING_TOGGLE`.
`SH_TT` swap-hands tap-toggle key is similar to [layer tap-toggle](feature_layers.md?id=switching-and-toggling-layers). Tapping repeatedly (5 taps by default) will toggle swap-hands on or off, like `SH_TOGG`. Tap-toggle count can be changed by defining a value for `TAPPING_TOGGLE`.
## Encoder Mapping
@ -44,3 +44,9 @@ As an example, if a split keyboard has a single encoder per side, you can swap t
const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS] = { 1, 0 };
#endif
```
### Functions :id=functions
| Function | Description |
|----------------------|---------------------------------------------|
| `is_swap_hands_on()` | Returns true if Swap-Hands is currently on. |

View file

@ -42,7 +42,7 @@ For more complicated cases, like blink the LEDs, fiddle with the backlighting, a
Well, that's the bulk of it! You should now be able to work through the examples below, and to develop your own Tap Dance functionality. But if you want a deeper understanding of what's going on behind the scenes, then read on for the explanation of how it all works!
Let's go over the three functions mentioned in `ACTION_TAP_DANCE_FN_ADVANCED` in a little more detail. They all receive the same too arguments: a pointer to a structure that holds all dance related state information, and a pointer to a use case specific state variable. The three functions differ in when they are called. The first, `on_each_tap_fn()`, is called every time the tap dance key is *pressed*. Before it is called, the counter is incremented and the timer is reset. The second function, `on_dance_finished_fn()`, is called when the tap dance is interrupted or ends because `TAPPING_TERM` milliseconds have passed since the last tap. When the `finished` field of the dance state structure is set to `true`, the `on_dance_finished_fn()` is skipped. After `on_dance_finished_fn()` was called or would have been called, but no sooner than when the tap dance key is *released*, `on_dance_reset_fn()` is called. It is possible to end a tap dance immediately, skipping `on_dance_finished_fn()`, but not `on_dance_reset_fn`, by calling `reset_tap_dance(state)`.
Let's go over the three functions mentioned in `ACTION_TAP_DANCE_FN_ADVANCED` in a little more detail. They all receive the same two arguments: a pointer to a structure that holds all dance related state information, and a pointer to a use case specific state variable. The three functions differ in when they are called. The first, `on_each_tap_fn()`, is called every time the tap dance key is *pressed*. Before it is called, the counter is incremented and the timer is reset. The second function, `on_dance_finished_fn()`, is called when the tap dance is interrupted or ends because `TAPPING_TERM` milliseconds have passed since the last tap. When the `finished` field of the dance state structure is set to `true`, the `on_dance_finished_fn()` is skipped. After `on_dance_finished_fn()` was called or would have been called, but no sooner than when the tap dance key is *released*, `on_dance_reset_fn()` is called. It is possible to end a tap dance immediately, skipping `on_dance_finished_fn()`, but not `on_dance_reset_fn`, by calling `reset_tap_dance(state)`.
To accomplish this logic, the tap dance mechanics use three entry points. The main entry point is `process_tap_dance()`, called from `process_record_quantum()` *after* `process_record_kb()` and `process_record_user()`. This function is responsible for calling `on_each_tap_fn()` and `on_dance_reset_fn()`. In order to handle interruptions of a tap dance, another entry point, `preprocess_tap_dance()` is run right at the beginning of `process_record_quantum()`. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. Finally, `tap_dance_task()` periodically checks whether `TAPPING_TERM` has passed since the last key press and finishes a tap dance if that is the case.
@ -64,7 +64,7 @@ enum {
};
// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
// Tap once for Escape, twice for Caps Lock
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
};
@ -96,14 +96,14 @@ enum {
#### Example 1: Send "Safety Dance!" After 100 Taps :id=example-1
```c
void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
void dance_egg(tap_dance_state_t *state, void *user_data) {
if (state->count >= 100) {
SEND_STRING("Safety dance!");
reset_tap_dance(state);
}
}
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
};
```
@ -113,7 +113,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
```c
// On each tap, light up one LED, from right to left
// On the fourth tap, turn them off from right to left
void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
void dance_flsh_each(tap_dance_state_t *state, void *user_data) {
switch (state->count) {
case 1:
ergodox_right_led_3_on();
@ -134,14 +134,14 @@ void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
}
// On the fourth tap, set the keyboard on flash state
void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
void dance_flsh_finished(tap_dance_state_t *state, void *user_data) {
if (state->count >= 4) {
reset_keyboard();
}
}
// If the flash state didn't happen, then turn off LEDs, left to right
void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
void dance_flsh_reset(tap_dance_state_t *state, void *user_data) {
ergodox_right_led_1_off();
wait_ms(50);
ergodox_right_led_2_off();
@ -150,7 +150,7 @@ void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
}
// All tap dances now put together. Example 2 is "CT_FLSH"
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
[CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
@ -169,7 +169,7 @@ typedef struct {
} tap_dance_tap_hold_t;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
qk_tap_dance_action_t *action;
tap_dance_action_t *action;
switch (keycode) {
case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations
@ -182,7 +182,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true;
}
void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
void tap_dance_tap_hold_finished(tap_dance_state_t *state, void *user_data) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
if (state->pressed) {
@ -200,7 +200,7 @@ void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
}
}
void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
void tap_dance_tap_hold_reset(tap_dance_state_t *state, void *user_data) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
if (tap_hold->held) {
@ -212,7 +212,7 @@ void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
{ .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
};
```
@ -256,11 +256,11 @@ enum {
SOME_OTHER_DANCE
};
td_state_t cur_dance(qk_tap_dance_state_t *state);
td_state_t cur_dance(tap_dance_state_t *state);
// For the x tap dance. Put it here so it can be used in any keymap
void x_finished(qk_tap_dance_state_t *state, void *user_data);
void x_reset(qk_tap_dance_state_t *state, void *user_data);
void x_finished(tap_dance_state_t *state, void *user_data);
void x_reset(tap_dance_state_t *state, void *user_data);
```
Now, at the bottom of your `keymap.c` file, you'll need to add the following:
@ -293,7 +293,7 @@ Now, at the bottom of your `keymap.c` file, you'll need to add the following:
* For the third point, there does exist the 'TD_DOUBLE_SINGLE_TAP', however this is not fully tested
*
*/
td_state_t cur_dance(qk_tap_dance_state_t *state) {
td_state_t cur_dance(tap_dance_state_t *state) {
if (state->count == 1) {
if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
// Key has not been interrupted, but the key is still held. Means you want to send a 'HOLD'.
@ -322,7 +322,7 @@ static td_tap_t xtap_state = {
.state = TD_NONE
};
void x_finished(qk_tap_dance_state_t *state, void *user_data) {
void x_finished(tap_dance_state_t *state, void *user_data) {
xtap_state.state = cur_dance(state);
switch (xtap_state.state) {
case TD_SINGLE_TAP: register_code(KC_X); break;
@ -337,7 +337,7 @@ void x_finished(qk_tap_dance_state_t *state, void *user_data) {
}
}
void x_reset(qk_tap_dance_state_t *state, void *user_data) {
void x_reset(tap_dance_state_t *state, void *user_data) {
switch (xtap_state.state) {
case TD_SINGLE_TAP: unregister_code(KC_X); break;
case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
@ -349,15 +349,13 @@ void x_reset(qk_tap_dance_state_t *state, void *user_data) {
xtap_state.state = TD_NONE;
}
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
};
```
And then simply use `TD(X_CTL)` anywhere in your keymap.
If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace.
> In this configuration "hold" takes place **after** tap dance timeout. To achieve instant hold, remove `state->interrupted` checks in conditions. As a result you may use comfortable longer tapping periods to have more time for taps and not to wait too long for holds (try starting with doubled `TAPPING_TERM`).
#### Example 5: Using tap dance for advanced mod-tap and layer-tap keys :id=example-5
@ -387,18 +385,18 @@ static td_state_t td_state;
// Declare your tapdance functions:
// Function to determine the current tapdance state
td_state_t cur_dance(qk_tap_dance_state_t *state);
td_state_t cur_dance(tap_dance_state_t *state);
// `finished` and `reset` functions for each tapdance keycode
void altlp_finished(qk_tap_dance_state_t *state, void *user_data);
void altlp_reset(qk_tap_dance_state_t *state, void *user_data);
void altlp_finished(tap_dance_state_t *state, void *user_data);
void altlp_reset(tap_dance_state_t *state, void *user_data);
```
Below your `LAYOUT`, define each of the tapdance functions:
```c
// Determine the tapdance state to return
td_state_t cur_dance(qk_tap_dance_state_t *state) {
td_state_t cur_dance(tap_dance_state_t *state) {
if (state->count == 1) {
if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
else return TD_SINGLE_HOLD;
@ -410,7 +408,7 @@ td_state_t cur_dance(qk_tap_dance_state_t *state) {
// Handle the possible states for each tapdance keycode you define:
void altlp_finished(qk_tap_dance_state_t *state, void *user_data) {
void altlp_finished(tap_dance_state_t *state, void *user_data) {
td_state = cur_dance(state);
switch (td_state) {
case TD_SINGLE_TAP:
@ -428,7 +426,7 @@ void altlp_finished(qk_tap_dance_state_t *state, void *user_data) {
}
}
void altlp_reset(qk_tap_dance_state_t *state, void *user_data) {
void altlp_reset(tap_dance_state_t *state, void *user_data) {
switch (td_state) {
case TD_SINGLE_TAP:
unregister_code16(KC_LPRN);
@ -445,7 +443,7 @@ void altlp_reset(qk_tap_dance_state_t *state, void *user_data) {
}
// Define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
};
```
@ -480,18 +478,18 @@ enum {
// Declare the functions to be used with your tap dance key(s)
// Function associated with all tap dances
td_state_t cur_dance(qk_tap_dance_state_t *state);
td_state_t cur_dance(tap_dance_state_t *state);
// Functions associated with individual tap dances
void ql_finished(qk_tap_dance_state_t *state, void *user_data);
void ql_reset(qk_tap_dance_state_t *state, void *user_data);
void ql_finished(tap_dance_state_t *state, void *user_data);
void ql_reset(tap_dance_state_t *state, void *user_data);
```
Towards the bottom of your `keymap.c`, include the following code:
```c
// Determine the current tap dance state
td_state_t cur_dance(qk_tap_dance_state_t *state) {
td_state_t cur_dance(tap_dance_state_t *state) {
if (state->count == 1) {
if (!state->pressed) return TD_SINGLE_TAP;
else return TD_SINGLE_HOLD;
@ -506,7 +504,7 @@ static td_tap_t ql_tap_state = {
};
// Functions that control what our tap dance key does
void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
void ql_finished(tap_dance_state_t *state, void *user_data) {
ql_tap_state.state = cur_dance(state);
switch (ql_tap_state.state) {
case TD_SINGLE_TAP:
@ -530,7 +528,7 @@ void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
}
}
void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
void ql_reset(tap_dance_state_t *state, void *user_data) {
// If the key was held down and now is released then switch off the layer
if (ql_tap_state.state == TD_SINGLE_HOLD) {
layer_off(_MY_LAYER);
@ -539,7 +537,7 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
}
// Associate our tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
tap_dance_action_t tap_dance_actions[] = {
[QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset)
};

View file

@ -1,10 +0,0 @@
# Thermal Printer
<!-- FIXME: Describe thermal printers support here. -->
## Thermal Printer Keycodes
|Key |Description |
|-----------|----------------------------------------|
|`PRINT_ON` |Start printing everything the user types|
|`PRINT_OFF`|Stop printing everything the user types |

48
docs/feature_tri_layer.md Normal file
View file

@ -0,0 +1,48 @@
# Tri Layers :id=tri-layers
This enables support for the OLKB style "Tri Layer" keycodes. These function similar to the `MO` (momentary) function key, but if both the "Lower" and "Upper" keys are pressed, it activates a third "Adjust" layer. To enable this functionality, add this line to your `rules.mk`:
```make
TRI_LAYER_ENABLE = yes
```
Note that the "upper", "lower" and "adjust" names don't have a particular significance, they are just used to identify and clarify the behavior. Layers are processed from highest numeric value to lowest, however the values are not required to be consecutive.
For a detailed explanation of how the layer stack works, check out [Keymap Overview](keymap.md#keymap-and-layers).
## Keycodes :id=keycodes
| Keycode | Alias | Description |
|----------------------|-----------|---------------------------------------------------------------------------------------------------------|
| `QK_TRI_LAYER_LOWER` | `TL_LOWR` | Momentarily enables the "lower" layer. Enables the "adjust" layer if the "upper" layer is also enabled" |
| `QK_TRI_LAYER_UPPER` | `TL_UPPR` | Momentarily enables the "upper" layer. Enables the "adjust" layer if the "lower" layer is also enabled" |
## Configuration
To change the default values for the layers, you can change these defines, in your `config.h`
| Config name | Default | Description |
|--------------------------|---------|------------------------------------------|
| `TRI_LAYER_LOWER_LAYER` | `1` | Sets the default for the "lower" layer. |
| `TRI_LAYER_UPPER_LAYER` | `2` | Sets the default for the "upper" layer. |
| `TRI_LAYER_ADJUST_LAYER` | `3` | Sets the default for the "adjust" layer. |
Eg, if you wanted to set the "Adjust" layer to be layer 5, you'd add this to your `config.h`:
```c
#define TRI_LAYER_ADJUST_LAYER 5
```
## Functions
| Function name | Description |
|----------------------------------------------|-------------------------------------------------|
| `set_tri_layer_lower_layer(layer)` | Changes the "lower" layer*. |
| `set_tri_layer_upper_layer(layer)` | Changes the "upper" layer*. |
| `set_tri_layer_adjust_layer(layer)` | Changes the "adjust" layer*. |
| `set_tri_layer_layers(lower, upper, adjust)` | Stes the "lower", "upper" and "adjust" layers*. |
| `get_tri_layer_lower_layer()` | Gets the current "lower" layer. |
| `get_tri_layer_upper_layer()` | Gets the current "upper" layer. |
| `get_tri_layer_adjust_layer()` | Gets the current "adjust" layer. |
!> Note: these settings are not persisent, and will be reset to the default on power loss or power cycling of the controller.

View file

@ -51,7 +51,7 @@ enum unicode_names {
SNEK
};
const uint32_t PROGMEM unicode_map[] = {
const uint32_t unicode_map[] PROGMEM = {
[BANG] = 0x203D, // ‽
[IRONY] = 0x2E2E, // ⸮
[SNEK] = 0x1F40D, // 🐍
@ -83,7 +83,7 @@ UCIS_ENABLE = yes
Then define a table like this in your keymap file:
```c
const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
UCIS_SYM("poop", 0x1F4A9), // 💩
UCIS_SYM("rofl", 0x1F923), // 🤣
UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺
@ -93,15 +93,15 @@ const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file.
To use UCIS input, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
To use UCIS input, call `ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
#### Customization
There are several functions that you can define in your keymap to customize the functionality of this feature.
* `void qk_ucis_start_user(void)` This runs when you call the "start" function, and can be used to provide feedback. By default, it types out a keyboard emoji.
* `void qk_ucis_success(uint8_t symbol_index)` This runs when the input has matched something and has completed. By default, it doesn't do anything.
* `void qk_ucis_symbol_fallback (void)` This runs when the input doesn't match anything. By default, it falls back to trying that input as a Unicode code.
* `void ucis_start_user(void)` This runs when you call the "start" function, and can be used to provide feedback. By default, it types out a keyboard emoji.
* `void ucis_success(uint8_t symbol_index)` This runs when the input has matched something and has completed. By default, it doesn't do anything.
* `void ucis_symbol_fallback (void)` This runs when the input doesn't match anything. By default, it falls back to trying that input as a Unicode code.
You can find the default implementations of these functions in [`process_ucis.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c).
@ -112,30 +112,28 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort
The following input modes are available:
* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).
* **`UNICODE_MODE_MACOS`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).
To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.
By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with a different keycode.
!> Using the _Unicode Hex Input_ input source may disable some Option-based shortcuts, such as Option+Left and Option+Right.
!> `UC_OSX` is a deprecated alias of `UC_MAC` that will be removed in future versions of QMK. All new keymaps should use `UC_MAC`.
* **`UC_LNX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points).
* **`UNICODE_MODE_LINUX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points).
Enabled by default and works almost anywhere on IBus-enabled distros. Without IBus, this mode works under GTK apps, but rarely anywhere else.
By default, this mode uses Ctrl+Shift+U (`LCTL(LSFT(KC_U))`) to start Unicode input, but this can be changed by defining [`UNICODE_KEY_LNX`](#input-key-configuration) with a different keycode. This might be required for IBus versions ≥1.5.15, where Ctrl+Shift+U behavior is consolidated into Ctrl+Shift+E.
Users who wish support in non-GTK apps without IBus may need to resort to a more indirect method, such as creating a custom keyboard layout ([more on this method](#custom-linux-layout)).
* **`UC_WIN`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`.
* **`UNICODE_MODE_WINDOWS`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`.
To enable, create a registry key under `HKEY_CURRENT_USER\Control Panel\Input Method` of type `REG_SZ` called `EnableHexNumpad` and set its value to `1`. This can be done from the Command Prompt by running `reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1` with administrator privileges. Reboot afterwards.
This mode is not recommended because of reliability and compatibility issues; use the `UC_WINC` mode instead.
This mode is not recommended because of reliability and compatibility issues; use the `UNICODE_MODE_WINCOMPOSE` mode instead.
* **`UC_BSD`**: _(non implemented)_ Unicode input under BSD. Not implemented at this time. If you're a BSD user and want to help add support for it, please [open an issue on GitHub](https://github.com/qmk/qmk_firmware/issues).
* **`UNICODE_MODE_BSD`**: _(non implemented)_ Unicode input under BSD. Not implemented at this time. If you're a BSD user and want to help add support for it, please [open an issue on GitHub](https://github.com/qmk/qmk_firmware/issues).
* **`UC_WINC`**: Windows Unicode input using [WinCompose](https://github.com/samhocevar/wincompose). As of v0.9.0, supports code points up to `0x10FFFF` (all possible code points).
* **`UNICODE_MODE_WINCOMPOSE`**: Windows Unicode input using [WinCompose](https://github.com/samhocevar/wincompose). As of v0.9.0, supports code points up to `0x10FFFF` (all possible code points).
To enable, install the [latest release](https://github.com/samhocevar/wincompose/releases/latest). Once installed, WinCompose will automatically run on startup. This mode works reliably under all version of Windows supported by the app.
By default, this mode uses right Alt (`KC_RALT`) as the Compose key, but this can be changed in the WinCompose settings and by defining [`UNICODE_KEY_WINC`](#input-key-configuration) with a different keycode.
@ -146,15 +144,15 @@ The following input modes are available:
To set your desired input mode, add the following define to your `config.h`:
```c
#define UNICODE_SELECTED_MODES UC_LNX
#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
```
This example sets the board's default input mode to `UC_LNX`. You can replace this with `UC_MAC`, `UC_WINC`, or any of the other modes listed [above](#input-modes). The board will automatically use the selected mode on startup, unless you manually switch to another mode (see [below](#keycodes)).
This example sets the board's default input mode to `UNICODE_MODE_LINUX`. You can replace this with `UNICODE_MODE_MACOS`, `UNICODE_MODE_WINCOMPOSE`, or any of the other modes listed [above](#input-modes). The board will automatically use the selected mode on startup, unless you manually switch to another mode (see [below](#keycodes)).
You can also select multiple input modes, which allows you to easily cycle through them using the `UC_MOD`/`UC_RMOD` keycodes.
You can also select multiple input modes, which allows you to easily cycle through them using the `UC_NEXT`/`UC_PREV` keycodes.
```c
#define UNICODE_SELECTED_MODES UC_MAC, UC_LNX, UC_WINC
#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_LINUX, UNICODE_MODE_WINCOMPOSE
```
Note that the values are separated by commas. The board will remember the last used input mode and will continue using it on next power-up. You can disable this and force it to always start with the first mode in the list by adding `#define UNICODE_CYCLE_PERSIST false` to your `config.h`.
@ -163,18 +161,18 @@ Note that the values are separated by commas. The board will remember the last u
You can switch the input mode at any time by using the following keycodes. Adding these to your keymap allows you to quickly switch to a specific input mode, including modes not listed in `UNICODE_SELECTED_MODES`.
|Keycode |Alias |Input Mode |Description |
|----------------------|---------|------------|-----------------------------------------------------------------------------|
|`UNICODE_MODE_FORWARD`|`UC_MOD` |Next in list|Cycle through selected modes, reverse direction when Shift is held |
|`UNICODE_MODE_REVERSE`|`UC_RMOD`|Prev in list|Cycle through selected modes in reverse, forward direction when Shift is held|
|`UNICODE_MODE_MAC` |`UC_M_MA`|`UC_MAC` |Switch to macOS input |
|`UNICODE_MODE_LNX` |`UC_M_LN`|`UC_LNX` |Switch to Linux input |
|`UNICODE_MODE_WIN` |`UC_M_WI`|`UC_WIN` |Switch to Windows input |
|`UNICODE_MODE_BSD` |`UC_M_BS`|`UC_BSD` |Switch to BSD input _(not implemented)_ |
|`UNICODE_MODE_WINC` |`UC_M_WC`|`UC_WINC` |Switch to Windows input using WinCompose |
|`UNICODE_MODE_EMACS` |`UC_M_EM`|`UC_EMACS` |Switch to emacs (`C-x-8 RET`) |
|Keycode |Alias |Input Mode |Description |
|----------------------------|---------|-------------------------|-----------------------------------------------------------------------------|
|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Next in list |Cycle through selected modes, reverse direction when Shift is held |
|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Prev in list |Cycle through selected modes in reverse, forward direction when Shift is held|
|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |`UNICODE_MODE_MACOS` |Switch to macOS input |
|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|`UNICODE_MODE_LINUX` |Switch to Linux input |
|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |`UNICODE_MODE_WINDOWS` |Switch to Windows input |
|`QK_UNICODE_MODE_BSD` |`UC_BSD` |`UNICODE_MODE_BSD` |Switch to BSD input _(not implemented)_ |
|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|`UNICODE_MODE_WINCOMPOSE`|Switch to Windows input using WinCompose |
|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|`UNICODE_MODE_EMACS` |Switch to emacs (`C-x-8 RET`) |
You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UC_LNX`).
You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UNICODE_MODE_LINUX`).
?> Using `UNICODE_SELECTED_MODES` is preferable to calling `set_unicode_input_mode()` in `matrix_init_user()` or similar functions, since it's better integrated into the Unicode system and has the added benefit of avoiding unnecessary writes to EEPROM.
@ -206,6 +204,17 @@ The functions for starting and finishing Unicode input on your platform can be o
You can find the default implementations of these functions in [`process_unicode_common.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode_common.c).
### Input Mode Callbacks
There are callbacks functions available that are called whenever the unicode input mode changes. The new input mode is passed to the function.
|Callback |Description |
|---------------------------------------------------|-----------------------------------------------------|
| `unicode_input_mode_set_kb(uint8_t input_mode)` | Callback for unicode input mode set, for keyboard. |
| `unicode_input_mode_set_user(uint8_t input_mode)` | Callback for unicode input mode set, for users. |
This feature can be used, for instance, to implement LED indicators for the current unicode input mode.
### Input Key Configuration
You can customize the keys used to trigger Unicode input for macOS, Linux and WinCompose by adding corresponding defines to your `config.h`. The default values match the platforms' default settings, so you shouldn't need to change this unless Unicode input isn't working, or you want to use a different key (e.g. in order to free up left or right Alt).

View file

@ -12,7 +12,7 @@ EXTRAKEY_ENABLE = yes
VELOCIKEY_ENABLE = yes
```
Then, while using your keyboard, you need to also turn it on with the `VLK_TOG` keycode, which toggles the feature on and off.
Then, while using your keyboard, you need to also turn it on with the `VK_TOGG` keycode, which toggles the feature on and off.
The following light effects will all be controlled by Velocikey when it is enabled:
- RGB Breathing

View file

@ -34,7 +34,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Press the `RESET` keycode
* Press the `QK_BOOT` keycode
* Press the `RESET` button on the PCB if available
* Short RST to GND quickly
2. Wait for the OS to detect the device
@ -87,7 +87,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods (you only have 7 seconds to flash once it enters; some variants may require you to reset twice within 750 milliseconds):
* Press the `RESET` keycode
* Press the `QK_BOOT` keycode
* Press the `RESET` button on the PCB if available
* Short RST to GND quickly
2. Wait for the OS to detect the device
@ -123,7 +123,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods (you only have 7 seconds to flash once it enters):
* Press the `RESET` keycode
* Press the `QK_BOOT` keycode
* Press the `RESET` button on the Teensy or PCB if available
* short RST to GND quickly
2. Wait for the OS to detect the device
@ -153,7 +153,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Press the `RESET` keycode
* Press the `QK_BOOT` keycode
* Keep the `BOOT` button held while quickly tapping the `RESET` button on the PCB
2. Wait for the OS to detect the device
3. Flash a .hex file
@ -182,7 +182,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode
* Tap the `QK_BOOT` keycode
* Hold the salt key while plugging the keyboard in - for PS2AVRGB boards, this is usually the key connected to MCU pins A0 and B0, otherwise it will be documented in your keyboard's readme
2. Wait for the OS to detect the device
3. Flash a .hex file
@ -223,7 +223,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Press the `RESET` keycode
* Press the `QK_BOOT` keycode
* Press the `RESET` button on the PCB if available
* short RST to GND quickly
2. Wait for the OS to detect the device
@ -256,7 +256,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode (may not work on STM32F042 devices)
* Tap the `QK_BOOT` keycode (may not work on STM32F042 devices)
* If a reset circuit is present, tap the `RESET` button on the PCB; some boards may also have a toggle switch that must be flipped
* Otherwise, you need to bridge `BOOT0` to VCC (via `BOOT0` button or jumper), short `RESET` to GND (via `RESET` button or jumper), and then let go of the `BOOT0` bridge
2. Wait for the OS to detect the device
@ -292,7 +292,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode
* Tap the `QK_BOOT` keycode
* If a reset circuit is present, tap the `RESET` button on the PCB
* Otherwise, you need to bridge `BOOT0` to VCC (via `BOOT0` button or jumper), short `RESET` to GND (via `RESET` button or jumper), and then let go of the `BOOT0` bridge
2. Wait for the OS to detect the device
@ -316,7 +316,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode
* 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
@ -324,7 +324,7 @@ Flashing sequence:
## tinyuf2
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on the F401/F411 blackpill.
Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.
The `rules.mk` setting for this bootloader is `tinyuf2`, and can be specified at the keymap or user level.
@ -342,7 +342,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode
* Tap the `QK_BOOT` keycode
* Double-tap the `nRST` button on the PCB.
2. Wait for the OS to detect the device
3. Copy the .uf2 file to the new USB disk
@ -353,7 +353,7 @@ or
CLI Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode
* Tap the `QK_BOOT` keycode
* Double-tap the `nRST` button on the PCB.
2. Wait for the OS to detect the device
3. Flash via QMK CLI eg. `qmk flash --keyboard handwired/onekey/blackpill_f411_tinyuf2 --keymap default`
@ -363,6 +363,47 @@ CLI Flashing sequence:
* `:uf2-split-left` and `:uf2-split-right`: Flashes the firmware but also sets the handedness setting in EEPROM by generating a side specific firmware.
## uf2boot
Keyboards may opt into supporting the uf2boot bootloader. This is currently only supported on F103.
The `rules.mk` setting for this bootloader is `uf2boot`, and can be specified at the keymap or user level.
To ensure compatibility with the uf2boot bootloader, make sure this block is present in your `rules.mk`:
```make
# Bootloader selection
BOOTLOADER = uf2boot
```
Compatible flashers:
* Any application able to copy a file from one place to another, such as _macOS Finder_ or _Windows Explorer_.
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `QK_BOOT` keycode
* Double-tap the `nRST` button on the PCB.
2. Wait for the OS to detect the device
3. Copy the .uf2 file to the new USB disk
4. Wait for the keyboard to become available
or
CLI Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `QK_BOOT` keycode
* Double-tap the `nRST` button on the PCB.
2. Wait for the OS to detect the device
3. Flash via QMK CLI eg. `qmk flash --keyboard handwired/onekey/bluepill_uf2boot --keymap default`
4. Wait for the keyboard to become available
### `make` Targets
* `:uf2-split-left` and `:uf2-split-right`: Flashes the firmware but also sets the handedness setting in EEPROM by generating a side specific firmware.
## Raspberry Pi RP2040 UF2
The `rules.mk` setting for this bootloader is `rp2040`, and can be specified at the keymap or user level.
@ -381,7 +422,7 @@ Compatible flashers:
Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `QK_BOOTLOADER` keycode
* Tap the `QK_BOOT` keycode
* Hold the `BOOTSEL` button on the PCB while plugin in the usb cable.
* Double-tap the `RESET` button on the PCB<sup>1</sup>.
2. Wait for the OS to detect the device
@ -393,7 +434,7 @@ or
CLI Flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `QK_BOOTLOADER` keycode
* Tap the `QK_BOOT` keycode
* Hold the `BOOTSEL` button on the PCB while plugin in the usb cable.
* Double-tap the `RESET` button on the PCB<sup>1</sup>.
2. Wait for the OS to detect the device

View file

@ -5,7 +5,7 @@ ps2avr(GB) boards use an ATmega32A microcontroller and a different bootloader. I
General flashing sequence:
1. Enter the bootloader using any of the following methods:
* Tap the `RESET` keycode (may not work on all devices)
* Tap the `QK_BOOT` keycode (may not work on all devices)
* Hold the salt key while plugging the keyboard in (usually documented within keyboard readme)
2. Wait for the OS to detect the device
3. Flash a .hex file

View file

@ -30,7 +30,7 @@ The above functions are not always guaranteed to work atomically. Therefore, if
eg.
```c
void some_function() {
void some_function(void) {
// some process
ATOMIC_BLOCK_FORCEON {
// Atomic Processing

View file

@ -188,7 +188,7 @@ The following functions are typically defined in this file:
* `void matrix_init_kb(void)`
* `void matrix_scan_kb(void)`
* `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
* `void led_set_kb(uint8_t usb_led)`
* `bool led_update_kb(led_t led_state)`
### `<keyboard_name.h>`
@ -208,6 +208,8 @@ As an example, if you have a 60% PCB that supports ANSI and ISO you might define
| LAYOUT_ansi | default_ansi | An ANSI layout |
| LAYOUT_iso | default_iso | An ISO layout |
?> Providing only `LAYOUT_all` is invalid - especially when implementing the additional layouts within 3rd party tooling.
## Image/Hardware Files
In an effort to keep the repo size down we're no longer accepting binary files of any format, with few exceptions. Hosting them elsewhere (such as <https://imgur.com>) and linking them in the `readme.md` is preferred.

View file

@ -20,8 +20,8 @@
"layout": "LAYOUT_all",
"layers": [
["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_RO","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_MHEN","KC_SPC","KC_SPC","KC_HENK","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"],
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SLCK","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","RESET","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SCRL","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","QK_BOOT","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
]
}
```

View file

@ -162,8 +162,6 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
* `#define IGNORE_MOD_TAP_INTERRUPT`
* 両方のキーに `TAPPING_TERM` を適用することで、ホールド時に他のキーに変換するキーを使ってローリングコンボ (zx) をすることができるようにします
* 詳細は [Ignore Mod Tap Interrupt](ja/tap_hold.md#ignore-mod-tap-interrupt) を見てください
* `#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
* キーごとの `IGNORE_MOD_TAP_INTERRUPT` 設定の処理を有効にします
* `#define TAPPING_FORCE_HOLD`
* タップされた直後に、デュアルロールキーを修飾子として使用できるようにします
* [Tapping Force Hold](ja/tap_hold.md#tapping-force-hold)を見てください

View file

@ -83,7 +83,7 @@ void matrix_init(void) {
debounce_init(MATRIX_ROWS);
// 正しいキーボード動作のためにこれを呼び出す*必要があります*
matrix_init_quantum();
matrix_init_kb();
}
uint8_t matrix_scan(void) {
@ -95,7 +95,7 @@ uint8_t matrix_scan(void) {
changed = debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
// 正しいキーボード動作のためにこれを呼び出す*必要があります*
matrix_scan_quantum();
matrix_scan_kb();
return changed;
}

View file

@ -80,7 +80,7 @@ https://github.com/tmk/tmk_keyboard/issues/67
この機能を有効にした後で、キーマップでキーコード `KC_LCAP``KC_LNUM` および `KC_LSCR` を使います。
古いビンテージメカニカルキーボードにはロックスイッチが付いている場合がありますが、最新のものにはありません。***ほとんどの場合この機能は必要なく、単にキーコード `KC_CAPS``KC_NLCK` および `KC_SLCK`*** を使います。
古いビンテージメカニカルキーボードにはロックスイッチが付いている場合がありますが、最新のものにはありません。***ほとんどの場合この機能は必要なく、単にキーコード `KC_CAPS``KC_NUM` および `KC_SCRL`*** を使います。
## セディーユ 'Ç' のような ASCII 以外の特別文字の入力

View file

@ -13,7 +13,7 @@
あなたはおそらくキーボードを「文鎮化」したくないでしょう。文鎮化するとファームウェアを書き換えられないようになります。リスクがあまりに高い(そしてそうでないかもしれない)ものの一部のリストを示します。
- キーボードマップに RESET が含まれない場合、DFU モードに入るには、PCB のリセットボタンを押す必要があります。底部のネジを外す必要があります。
- キーボードマップに QK_BOOT が含まれない場合、DFU モードに入るには、PCB のリセットボタンを押す必要があります。底部のネジを外す必要があります。
- tmk_core / common にあるファイルを触るとキーボードが操作不能になるかもしれません。
- .hex ファイルが大きすぎると問題を引き起こします; `make dfu` コマンドはブロックを削除し、サイズを検査し(おっと、間違った順序です!)、エラーを出力し、
キーボードへの書き込みに失敗し、DFU モードのままになります。

View file

@ -23,7 +23,7 @@ Timer 3:
```
STARTUP_SONG // キーボードの起動時に再生 (audio.c)
GOODBYE_SONG // RESET キーを押すと再生 (quantum.c)
GOODBYE_SONG // QK_BOOT キーを押すと再生 (quantum.c)
AG_NORM_SONG // AG_NORM キーを押すと再生 (quantum.c)
AG_SWAP_SONG // AG_SWAP キーを押すと再生 (quantum.c)
CG_NORM_SONG // CG_NORM キーを押すと再生 (quantum.c)

View file

@ -9,7 +9,7 @@
## 使用法
キーマップ内の `KC_GRAVE` キー (通常は`1` キーの左)を `KC_GESC` に置き換えます。ほとんどの場合、このキーは押された時に `KC_ESC` を出力します。ただし、Shift あるいは GUI を押したままにすると、代わりに `KC_GRV` を出力します。
キーマップ内の `KC_GRAVE` キー (通常は`1` キーの左)を `QK_GESC` に置き換えます。ほとんどの場合、このキーは押された時に `KC_ESC` を出力します。ただし、Shift あるいは GUI を押したままにすると、代わりに `KC_GRV` を出力します。
## OS に見えるもの
@ -19,7 +19,7 @@
| キー | エイリアス | 説明 |
|---------|-----------|------------------------------------------------------------------|
| `KC_GESC` | `GRAVE_ESC` | 押された場合に Escape。Shift あるいは GUI が押されたままの場合は <code>&#96;</code> |
| `QK_GESC` | `GRAVE_ESC` | 押された場合に Escape。Shift あるいは GUI が押されたままの場合は <code>&#96;</code> |
### 注意事項

View file

@ -21,7 +21,7 @@
## 注意事項
キーロックは、標準アクションキーと[ワンショットモディファイア](ja/one_shot_keys.md)キー (例えば、Shift を `OSM(KC_LSFT)` と定義した場合)のみを押し続けることができます。
キーロックは、標準アクションキーと[ワンショットモディファイア](ja/one_shot_keys.md)キー (例えば、Shift を `OSM(MOD_LSFT)` と定義した場合)のみを押し続けることができます。
これは、QMK の特殊機能(ワンショットモディファイアを除く)、または `KC_LPRN` のような shift を押されたキーのバージョンは含みません。[基本的なキーコード](ja/keycodes_basic.md)リストにある場合、押したままにすることができます。
レイヤーの切り替えは、キーロックを解除しません。

View file

@ -22,7 +22,7 @@ QMK は HID 仕様で定義された5つの LED の読み取りメソッドを
LED の状態を `uint8_t` として提供する2つの非推奨の関数があります:
* `uint8_t led_set_kb(uint8_t usb_led)` と `_user(uint8_t usb_led)`
* `uint8_t led_set_user(uint8_t usb_led)`
* `uint8_t host_keyboard_leds()`
## 設定オプション :id=configuration-options

View file

@ -36,13 +36,14 @@ rules.mk で:
```makefile
PS2_MOUSE_ENABLE = yes
PS2_USE_BUSYWAIT = yes
PS2_ENABLE = yes
PS2_DRIVER = busywait
```
キーボードの config.h で:
```c
#ifdef PS2_USE_BUSYWAIT
#ifdef PS2_DRIVER_BUSYWAIT
# define PS2_CLOCK_PIN D1
# define PS2_DATA_PIN D2
#endif
@ -56,13 +57,14 @@ rules.mk で:
```makefile
PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes
PS2_ENABLE = yes
PS2_DRIVER = interrupt
```
キーボードの config.h で:
```c
#ifdef PS2_USE_INT
#ifdef PS2_DRIVER_INTERRUPT
#define PS2_CLOCK_PIN D2
#define PS2_DATA_PIN D5
@ -88,14 +90,14 @@ rules.mk で:
```makefile
PS2_MOUSE_ENABLE = yes
PS2_USE_USART = yes
PS2_ENABLE = yes
PS2_DRIVER = usart
```
キーボードの config.h で:
```c
#ifdef PS2_USE_USART
#ifdef PS2_USE_USART
#ifdef PS2_DRIVER_USART
#define PS2_CLOCK_PIN D5
#define PS2_DATA_PIN D2

View file

@ -340,8 +340,6 @@ qk_tap_dance_action_t tap_dance_actions[] = {
これで、キーマップのどこでも簡単に `TD(X_CTL)` マクロが使えます。
もし、この機能をユーザスペースで実現したい場合、 [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) がユーザスペースでどのように実装しているか確認してください。
> この設定の "hold" は、タップダンスのタイムアウト(`ACTION_TAP_DANCE_FN_ADVANCED_TIME` 参照)の **後** に起こります。即座に "hold" を得るためには、条件から `state->interrupted` の確認を除きます。結果として、複数回のタップのための時間をより多く持つことで快適な長いタップの期限を使うことができ、そして、"hold" のために長く待たないようにすることができます(2倍の `TAPPING TERM` で開始してみてください)。
#### 例5: タップダンスを高度なモッドタップとレイヤータップキーに使う :id=example-5

View file

@ -34,7 +34,7 @@ BOOTLOADER = atmel-dfu
書き込み手順:
1. `RESET` キーコードを押すか、RESET ボタンをタップします(または RST を GND にショートします)。
1. `QK_BOOT` キーコードを押すか、RESET ボタンをタップします(または RST を GND にショートします)。
2. OS がデバイスを検知するのを待ちます。
3. メモリを消去します(自動的に実行されるかもしれません)
4. .hex ファイルを書き込みます
@ -94,7 +94,7 @@ BOOTLOADER = caterina
書き込み手順:
1. `RESET` キーコードを押すか、RST をすばやく GND にショートします (入力後7秒で書き込みます)
1. `QK_BOOT` キーコードを押すか、RST をすばやく GND にショートします (入力後7秒で書き込みます)
2. OS がデバイスを検知するのを待ちます。
3. .hex ファイルを書き込みます
4. デバイスが自動的にリセットされるのを待ちます
@ -141,7 +141,7 @@ BOOTLOADER = halfkay
書き込み手順:
1. `RESET` キーコードを押すか、RST をすばやく GND にショートします (入力後7秒で書き込みます)
1. `QK_BOOT` キーコードを押すか、RST をすばやく GND にショートします (入力後7秒で書き込みます)
2. OS がデバイスを検知するのを待ちます。
3. .hex ファイルを書き込みます
4. デバイスをアプリケーションモードにリセットします(自動的に実行されるかもしれません)
@ -172,7 +172,7 @@ BOOTLOADER = USBasp
書き込み手順:
1. `RESET` キーコードを押すか、RST を GND にすばやくショートしながら、ブートピンを GND にショートしたままにします。
1. `QK_BOOT` キーコードを押すか、RST を GND にすばやくショートしながら、ブートピンを GND にショートしたままにします。
2. OS がデバイスを検知するのを待ちます。
3. .hex ファイルを書き込みます
4. デバイスをアプリケーションモードにリセットします(自動的に実行されるかもしれません)
@ -203,7 +203,7 @@ BOOTLOADER = bootloadHID
書き込み手順:
1. 以下のいずれかの方法を使ってブートローダに入ります:
* `RESET` キーコードをタップします (全てのデバイスでは動作しないかもしれません)
* `QK_BOOT` キーコードをタップします (全てのデバイスでは動作しないかもしれません)
* キーボードを接続しながらソルトキーを押し続けます (通常はキーボードの readme に書かれています)
2. OS がデバイスを検知するのを待ちます。
3. .hex ファイルを書き込みます
@ -227,7 +227,7 @@ BOOTLOADER = bootloadHID
書き込み手順:
1. 以下のいずれかの方法を使ってブートローダに入ります:
* `RESET` キーコードをタップします (STM32F042 デバイスでは動作しないかもしれません)
* `QK_BOOT` キーコードをタップします (STM32F042 デバイスでは動作しないかもしれません)
* リセット回路が存在する場合、RESET ボタンをタップします
* それ以外の場合は、(BOOT0 ボタンあるいはブリッジ経由で)BOOT0 を VCC にブリッジし、(REEST ボタンあるいはブリッジ経由で)RESET を GND にショートし、BOOT0 ブリッジを放す必要があります。
2. OS がデバイスを検知するのを待ちます。

View file

@ -10,7 +10,7 @@ ps2avr(GB) キーボードは ATmega32A マイクロコントローラを使い
一般的な書き込みシーケンス:
1. 以下のいずれかの方法を使ってブートローダに入ります:
* `RESET` キーコードをタップします (全てのデバイスでは動作しないかもしれません)
* `QK_BOOT` キーコードをタップします (全てのデバイスでは動作しないかもしれません)
* ソルトキーを押し続けながらキーボードを接続します (通常はキーボードの readme に書かれています)
2. OS がデバイスを検知するのを待ちます。
3. .hex ファイルを書き込みます

View file

@ -165,7 +165,7 @@ Clueboard は、サブフォルダをまとめるためとキーボードのリ
* `void matrix_init_kb(void)`
* `void matrix_scan_kb(void)`
* `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
* `void led_set_kb(uint8_t usb_led)`
* `bool led_update_kb(led_t led_state)`
### `<keyboard_name.h>`

View file

@ -87,7 +87,7 @@
|`KC_F11` | |F11 |✔ |✔ |✔ |
|`KC_F12` | |F12 |✔ |✔ |✔ |
|`KC_PSCREEN` |`KC_PSCR` |Print Screen |✔ |✔<sup>2</sup>|✔ |
|`KC_SCROLLLOCK` |`KC_SLCK`, `KC_BRMD` |Scroll Lock, 画面の明るさダウン (macOS) |✔ |✔<sup>2</sup>|✔ |
|`KC_SCROLLLOCK` |`KC_SCRL`, `KC_BRMD` |Scroll Lock, 画面の明るさダウン (macOS) |✔ |✔<sup>2</sup>|✔ |
|`KC_PAUSE` |`KC_PAUS`, `KC_BRK`, `KC_BRMU`|Pause, 画面の明るさアップ (macOS) |✔ |✔<sup>2</sup>|✔ |
|`KC_INSERT` |`KC_INS` |Insert |✔ | |✔ |
|`KC_HOME` | |Home |✔ |✔ |✔ |
@ -99,7 +99,7 @@
|`KC_LEFT` | |左矢印 |✔ |✔ |✔ |
|`KC_DOWN` | |下矢印 |✔ |✔ |✔ |
|`KC_UP` | |上矢印 |✔ |✔ |✔ |
|`KC_NUMLOCK` |`KC_NLCK` |テンキー Num Lock と Clear |✔ |✔ |✔ |
|`KC_NUMLOCK` |`KC_NUM` |テンキー Num Lock と Clear |✔ |✔ |✔ |
|`KC_KP_SLASH` |`KC_PSLS` |テンキー `/` |✔ |✔ |✔ |
|`KC_KP_ASTERISK` |`KC_PAST` |テンキー `*` |✔ |✔ |✔ |
|`KC_KP_MINUS` |`KC_PMNS` |テンキー `-` |✔ |✔ |✔ |
@ -228,10 +228,10 @@
[Quantum キーコード](ja/quantum_keycodes.md#qmk-keycodes) も見てください。
|キー |エイリアス |説明 |
|--------------|-----------|---------------------------------------------------------|
|`RESET` | |ファームウエア書き込みのためにキーボードをブートローダーモードにします |
|`DEBUG` | |デバッグモードを切り替えます |
|`EEPROM_RESET`|`EEP_RST` |キーボードの EEPROM (不揮発メモリ) を再初期化します |
|-----------------|---------|---------------------------------------------------------|
|`QK_BOOTLOADER` |`QK_BOOT`|ファームウエア書き込みのためにキーボードをブートローダーモードにします |
|`QK_DEBUG_TOGGLE`|`DB_TOGG`|デバッグモードを切り替えます |
|`QK_CLEAR_EEPROM`|`EE_CLR` |キーボードの EEPROM (不揮発メモリ) を再初期化します |
## オーディオキー :id=audio-keys

View file

@ -105,8 +105,8 @@
|キー |エイリアス |説明 |
|-------------------|--------------------|---------------------------------------|
|`KC_CAPSLOCK` |`KC_CLCK`, `KC_CAPS`|Caps Lock |
|`KC_SCROLLLOCK` |`KC_SLCK`, `KC_BRMD`|Scroll Lock, 画面の明るさダウン (macOS)|
|`KC_NUMLOCK` |`KC_NLCK` |テンキー Num Lock と Clear |
|`KC_SCROLLLOCK` |`KC_SCRL`, `KC_BRMD`|Scroll Lock, 画面の明るさダウン (macOS)|
|`KC_NUMLOCK` |`KC_NUM` |テンキー Num Lock と Clear |
|`KC_LOCKING_CAPS` |`KC_LCAP` |Caps Lock のロック |
|`KC_LOCKING_NUM` |`KC_LNUM` |Num Lock のロック |
|`KC_LOCKING_SCROLL`|`KC_LSCR` |Scroll Lock のロック |

View file

@ -121,9 +121,11 @@ TMK の歴史的経緯から、キーマップに保存されたアクション
// STUFF あるいは他の名前のレイヤーを持つことができます。
// レイヤー名は全て同じ長さである必要はなく、
// また名前を完全に省略して単に数字を使うことができます。
#define _BL 0
#define _FL 1
#define _CL 2
enum layer_names {
_BL,
_FL,
_CL,
};
これらはキーマップとカスタム関数を作成するときに使うことができる便利な定義です。`GRAVE_MODS` 定義は後でカスタム関数で使われ、その下の `_BL``_FL``_CL` 定義は各レイヤーを参照しやすくします。
@ -167,7 +169,7 @@ Clueboard の基本レイヤーの例です:
[_FL] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_DEL, BL_STEP, \
_______, _______, _______,_______,_______,_______,_______,_______,KC_PSCR,KC_SLCK, KC_PAUS, _______, _______, _______, _______, \
_______, _______, _______,_______,_______,_______,_______,_______,KC_PSCR,KC_SCRL, KC_PAUS, _______, _______, _______, _______, \
_______, _______, MO(_CL),_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, \
_______, _______, _______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, KC_PGUP, \
_______, _______, _______, _______, _______,_______, _______, _______, _______, MO(_FL), KC_HOME, KC_PGDN, KC_END),

View file

@ -106,10 +106,8 @@ VS Code のようなフル機能のエディタの使用は、プレーンテキ
* [Git Extension Pack](https://marketplace.visualstudio.com/items?itemName=donjayamanne.git-extension-pack) -
これは QMK ファームウェアで Git を簡単に使用できる Git 関連ツールを多数インスールします。
* [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - _[オプション]_ - QMK コーディング規約にコードを準拠させるのに役立ちます。
* [Bracket Pair Colorizer 2](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer-2) - _[オプション]_ - これはネストされたコードを参照しやすくするために、コード内の括弧を色分けします。
* [GitHub Markdown Preview](https://marketplace.visualstudio.com/items?itemName=bierner.github-markdown-preview) - _[オプション]_ - VS Code の markdown プレビューを GithHub のようにします。
* [VS Live Share Extension Pack](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack) - _[オプション]_ - この拡張により、他の誰かがあなたのワークスペースにアクセスし(あるいは、あなたが他の誰かのワークスペースにアクセスし)、手伝うことができます。あなたが問題を抱えており、他の誰かの助けが必要な場合に便利です。
* [VIM Keymap](https://marketplace.visualstudio.com/items?itemName=GiuseppeCesarano.vim-keymap) - _[オプション]_ - VIM スタイルのキーバインドを好む人向け。これには他のオプションもあります。
いずれかの拡張機能をインストールしたら、再起動します。

View file

@ -14,7 +14,7 @@ quantum 内の全てのキーコードは `0x0000` と `0xFFFF` の間の数値
## QMK キーコード :id=qmk-keycodes
| キー | エイリアス | 説明 |
|----------------|------------|--------------------------------------------------------|
| `RESET` | | 書き込みのために、キーボードを bootloader モードにする |
| `DEBUG` | | デバッグモードの切り替え |
| `EEPROM_RESET` | `EEP_RST` | キーボードの EEPROM (永続化メモリ) を再初期化する |
|-----------------|---------|--------------------------------------------------------|
|`QK_BOOTLOADER` |`QK_BOOT`| 書き込みのために、キーボードを bootloader モードにする |
|`QK_DEBUG_TOGGLE`|`DB_TOGG`| デバッグモードの切り替え |
|`QK_CLEAR_EEPROM`|`EE_CLR` | キーボードの EEPROM (永続化メモリ) を再初期化する |

View file

@ -173,7 +173,7 @@ Configurator の API は、指定されたレイアウトマクロと JSON フ
| k40 | {"label":"0", "x":0, "y":4, "w":2} |
| k42 | {"label":".", "x":2, "y":4} |
ユーザが Configurator で左上のキーを選択し、Num Lock を割り当てると、Configurator は最初のキーとして `KC_NLCK` を持つキーマップを作成し、同様にキーマップが作成されます。`label` キーは使われません; それらは `info.json` ファイルをデバッグする時に特定のキーを識別するためのユーザの参照のためだけのものです。
ユーザが Configurator で左上のキーを選択し、Num Lock を割り当てると、Configurator は最初のキーとして `KC_NUM` を持つキーマップを作成し、同様にキーマップが作成されます。`label` キーは使われません; それらは `info.json` ファイルをデバッグする時に特定のキーを識別するためのユーザの参照のためだけのものです。
## 問題と危険

View file

@ -110,25 +110,6 @@ bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) {
?> `許容ホールド`を有効にすると、これは両方がどのように動作するかを変更します。通常のキーには、最初のキーが最初に放された場合、あるいは両方のキーが `TAPPING_TERM` より長くホールドされた場合に、修飾キーが追加されます。
この機能をより細かく制御するために、以下を `config.h` に追加することができます:
```c
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
```
そして、以下の関数をキーマップに追加します:
```c
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case SFT_T(KC_SPC):
return true;
default:
return false;
}
}
```
## タッピング強制ホールド
`タッピング強制ホールド` を有効にするには、以下を `config.h` に追加します:

View file

@ -91,7 +91,7 @@ QMK は他のコンピュータプログラムと何ら変わりないと考え
```
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
KC_NUM, KC_PSLS, KC_PAST, KC_PMNS, \
KC_P7, KC_P8, KC_P9, KC_PPLS, \
KC_P4, KC_P5, KC_P6, \
KC_P1, KC_P2, KC_P3, KC_PENT, \
@ -129,7 +129,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
}
```
キーマップと比較すると、押されたキーが KC_NLCK であることが分かります。ここから、`process_record` 関数群を呼び出します。
キーマップと比較すると、押されたキーが KC_NUM であることが分かります。ここから、`process_record` 関数群を呼び出します。
<!-- FIXME: Magic happens between here and process_record -->

View file

@ -207,6 +207,10 @@ See also: [Basic Keycodes](keycodes_basic.md)
|`KC_MEDIA_REWIND` |`KC_MRWD` |Previous Track |✔<sup>6</sup>|✔<sup>5</sup>|✔ |
|`KC_BRIGHTNESS_UP` |`KC_BRIU` |Brightness Up |✔ |✔ |✔ |
|`KC_BRIGHTNESS_DOWN` |`KC_BRID` |Brightness Down |✔ |✔ |✔ |
|`KC_CONTROL_PANEL` |`KC_CPNL` |Open Control Panel |✔ | | |
|`KC_ASSISTANT` |`KC_ASST` |Launch Context-Aware Assistant |✔ | | |
|`KC_MISSION_CONTROL` |`KC_MCTL` |Open Mission Control | |✔ | |
|`KC_LAUNCHPAD` |`KC_LPAD` |Open Launchpad | |✔ | |
<sup>1. The Linux kernel HID driver recognizes [nearly all keycodes](https://github.com/torvalds/linux/blob/master/drivers/hid/hid-input.c), but the default bindings depend on the DE/WM.</sup><br/>
<sup>2. Treated as F13-F15.</sup><br/>
@ -231,63 +235,90 @@ See also: [Quantum Keycodes](quantum_keycodes.md#qmk-keycodes)
See also: [Audio](feature_audio.md)
|Key |Aliases |Description |
|----------------|---------|----------------------------------|
|`AU_ON` | |Turns on Audio Feature |
|`AU_OFF` | |Turns off Audio Feature |
|`AU_TOG` | |Toggles Audio state |
|`CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|`CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|`CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|`CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|`MU_ON` | |Turns on Music Mode |
|`MU_OFF` | |Turns off Music Mode |
|`MU_TOG` | |Toggles Music Mode |
|`MU_MOD` | |Cycles through the music modes |
|Key |Aliases |Description |
|-------------------------|---------|-------------------------------------------|
|`QK_AUDIO_ON` |`AU_ON` |Turns on Audio Feature |
|`QK_AUDIO_OFF` |`AU_OFF` |Turns off Audio Feature |
|`QK_AUDIO_TOGGLE` |`AU_TOGG`|Toggles Audio state |
|`QK_AUDIO_CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|`QK_AUDIO_CLICKY_ON` |`CK_ON` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_OFF` |`CK_OFF` |Turns on Audio clicky mode |
|`QK_AUDIO_CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|`QK_AUDIO_CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|`QK_AUDIO_CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|`QK_MUSIC_ON` |`MU_ON` |Turns on Music Mode |
|`QK_MUSIC_OFF` |`MU_OFF` |Turns off Music Mode |
|`QK_MUSIC_TOGGLE` |`MU_TOGG`|Toggles Music Mode |
|`QK_MUSIC_MODE_NEXT` |`MU_NEXT`|Cycles through the music modes |
|`QK_AUDIO_VOICE_NEXT` |`AU_NEXT`|Cycles through the audio voices |
|`QK_AUDIO_VOICE_PREVIOUS`|`AU_PREV`|Cycles through the audio voices in reverse |
## Auto Shift :id=auto-shift
See also: [Auto Shift](feature_auto_shift.md)
|Key |Aliases |Description |
|----------------------|---------|--------------------------------------------|
|`QK_AUTO_SHIFT_DOWN` |`AS_DOWN`|Lower the Auto Shift timeout variable (down)|
|`QK_AUTO_SHIFT_UP` |`AS_UP` |Raise the Auto Shift timeout variable (up) |
|`QK_AUTO_SHIFT_REPORT`|`AS_RPT` |Report your current Auto Shift timeout value|
|`QK_AUTO_SHIFT_ON` |`AS_ON` |Turns on the Auto Shift Function |
|`QK_AUTO_SHIFT_OFF` |`AS_OFF` |Turns off the Auto Shift Function |
|`QK_AUTO_SHIFT_TOGGLE`|`AS_TOGG`|Toggles the state of the Auto Shift feature |
## Autocorrect :id=autocorrect
See also: [Autocorrect](feature_autocorrect.md)
|Key |Aliases |Description |
|-----------------------|---------|----------------------------------------------|
|`QK_AUTOCORRECT_ON` |`AC_ON` |Turns on the Autocorrect feature. |
|`QK_AUTOCORRECT_OFF` |`AC_OFF` |Turns off the Autocorrect feature. |
|`QK_AUTOCORRECT_TOGGLE`|`AC_TOGG`|Toggles the status of the Autocorrect feature.|
## Backlighting :id=backlighting
See also: [Backlighting](feature_backlight.md)
|Key |Description |
|---------|------------------------------------------|
|`BL_TOGG`|Turn the backlight on or off |
|`BL_STEP`|Cycle through backlight levels |
|`BL_ON` |Set the backlight to max brightness |
|`BL_OFF` |Turn the backlight off |
|`BL_INC` |Increase the backlight level |
|`BL_DEC` |Decrease the backlight level |
|`BL_BRTG`|Toggle backlight breathing |
| Key | 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 |
## Bluetooth :id=bluetooth
See also: [Bluetooth](feature_bluetooth.md)
|Key |Description |
|----------|----------------------------------------------|
|`OUT_AUTO`|Automatically switch between USB and Bluetooth|
|`OUT_USB` |USB only |
|`OUT_BT` |Bluetooth only |
|Key |Aliases |Description |
|---------------------|---------|----------------------------------------------|
|`QK_OUTPUT_AUTO` |`OU_AUTO`|Automatically switch between USB and Bluetooth|
|`QK_OUTPUT_USB` |`OU_USB` |USB only |
|`QK_OUTPUT_BLUETOOTH`|`OU_BT` |Bluetooth only |
## Caps Word :id=caps-word
See also: [Caps Word](feature_caps_word.md)
|Key |Aliases |Description |
|-----------|---------|------------------------------|
|`CAPS_WORD`|`CAPSWRD`|Toggles Caps Word |
|Key |Aliases |Description |
|---------------------|---------|------------------------------|
|`QK_CAPS_WORD_TOGGLE`|`CW_TOGG`|Toggles Caps Word |
## Dynamic Macros :id=dynamic-macros
See also: [Dynamic Macros](feature_dynamic_macros.md)
|Key |Aliases |Description |
|-----------------|---------|--------------------------------------------------|
|`DYN_REC_START1` |`DM_REC1`|Start recording Macro 1 |
|`DYN_REC_START2` |`DM_REC2`|Start recording Macro 2 |
|`DYN_MACRO_PLAY1`|`DM_PLY1`|Replay Macro 1 |
|`DYN_MACRO_PLAY2`|`DM_PLY2`|Replay Macro 2 |
|`DYN_REC_STOP` |`DM_RSTP`|Finish the macro that is currently being recorded.|
|Key |Aliases |Description |
|---------------------------------|---------|--------------------------------------------------|
|`QK_DYNAMIC_MACRO_RECORD_START_1`|`DM_REC1`|Start recording Macro 1 |
|`QK_DYNAMIC_MACRO_RECORD_START_2`|`DM_REC2`|Start recording Macro 2 |
|`QK_DYNAMIC_MACRO_PLAY_1` |`DM_PLY1`|Replay Macro 1 |
|`QK_DYNAMIC_MACRO_PLAY_2` |`DM_PLY2`|Replay Macro 2 |
|`QK_DYNAMIC_MACRO_RECORD_STOP` |`DM_RSTP`|Finish the macro that is currently being recorded.|
## Grave Escape :id=grave-escape
@ -297,13 +328,52 @@ See also: [Grave Escape](feature_grave_esc.md)
|-----------------|---------|------------------------------------------------------------------|
|`QK_GRAVE_ESCAPE`|`QK_GESC`|Escape when pressed, <code>&#96;</code> when Shift or GUI are held|
## Joystick :id=joystick
See also: [Joystick](feature_joystick.md)
|Key |Aliases|Description|
|-----------------------|-------|-----------|
|`QK_JOYSTICK_BUTTON_0` |`JS_0` |Button 0 |
|`QK_JOYSTICK_BUTTON_1` |`JS_1` |Button 1 |
|`QK_JOYSTICK_BUTTON_2` |`JS_2` |Button 2 |
|`QK_JOYSTICK_BUTTON_3` |`JS_3` |Button 3 |
|`QK_JOYSTICK_BUTTON_4` |`JS_4` |Button 4 |
|`QK_JOYSTICK_BUTTON_5` |`JS_5` |Button 5 |
|`QK_JOYSTICK_BUTTON_6` |`JS_6` |Button 6 |
|`QK_JOYSTICK_BUTTON_7` |`JS_7` |Button 7 |
|`QK_JOYSTICK_BUTTON_8` |`JS_8` |Button 8 |
|`QK_JOYSTICK_BUTTON_9` |`JS_9` |Button 9 |
|`QK_JOYSTICK_BUTTON_10`|`JS_10`|Button 10 |
|`QK_JOYSTICK_BUTTON_11`|`JS_11`|Button 11 |
|`QK_JOYSTICK_BUTTON_12`|`JS_12`|Button 12 |
|`QK_JOYSTICK_BUTTON_13`|`JS_13`|Button 13 |
|`QK_JOYSTICK_BUTTON_14`|`JS_14`|Button 14 |
|`QK_JOYSTICK_BUTTON_15`|`JS_15`|Button 15 |
|`QK_JOYSTICK_BUTTON_16`|`JS_16`|Button 16 |
|`QK_JOYSTICK_BUTTON_17`|`JS_17`|Button 17 |
|`QK_JOYSTICK_BUTTON_18`|`JS_18`|Button 18 |
|`QK_JOYSTICK_BUTTON_19`|`JS_19`|Button 19 |
|`QK_JOYSTICK_BUTTON_20`|`JS_20`|Button 20 |
|`QK_JOYSTICK_BUTTON_21`|`JS_21`|Button 21 |
|`QK_JOYSTICK_BUTTON_22`|`JS_22`|Button 22 |
|`QK_JOYSTICK_BUTTON_23`|`JS_23`|Button 23 |
|`QK_JOYSTICK_BUTTON_24`|`JS_24`|Button 24 |
|`QK_JOYSTICK_BUTTON_25`|`JS_25`|Button 25 |
|`QK_JOYSTICK_BUTTON_26`|`JS_26`|Button 26 |
|`QK_JOYSTICK_BUTTON_27`|`JS_27`|Button 27 |
|`QK_JOYSTICK_BUTTON_28`|`JS_28`|Button 28 |
|`QK_JOYSTICK_BUTTON_29`|`JS_29`|Button 29 |
|`QK_JOYSTICK_BUTTON_30`|`JS_30`|Button 30 |
|`QK_JOYSTICK_BUTTON_31`|`JS_31`|Button 31 |
## Key Lock :id=key-lock
See also: [Key Lock](feature_key_lock.md)
|Key |Description |
|---------|--------------------------------------------------------------|
|`KC_LOCK`|Hold down the next key pressed, until the key is pressed again|
|`QK_LOCK`|Hold down the next key pressed, until the key is pressed again|
## Layer Switching :id=layer-switching
@ -326,199 +396,200 @@ See also: [Leader Key](feature_leader_key.md)
|Key |Description |
|---------|------------------------|
|`KC_LEAD`|Begins a leader sequence|
|`QK_LEAD`|Begins a leader sequence|
## Magic Keycodes :id=magic-keycodes
See also: [Magic Keycodes](keycodes_magic.md)
|Key |Aliases |Description |
|----------------------------------|---------|--------------------------------------------------------------------------|
|`MAGIC_SWAP_CONTROL_CAPSLOCK` |`CL_SWAP`|Swap Caps Lock and Left Control |
|`MAGIC_UNSWAP_CONTROL_CAPSLOCK` |`CL_NORM`|Unswap Caps Lock and Left Control |
|`MAGIC_TOGGLE_CONTROL_CAPSLOCK` |`CL_TOGG`|Toggle Caps Lock and Left Control swap |
|`MAGIC_SWAP_ESCAPE_CAPSLOCK` |`EC_SWAP`|Swap Caps Lock and Escape |
|`MAGIC_UNSWAP_ESCAPE_CAPSLOCK` |`EC_NORM`|Unswap Caps Lock and Escape |
|`MAGIC_TOGGLE_ESCAPE_CAPSLOCK` |`EC_TOGG`|Toggle Caps Lock and Escape swap |
|`MAGIC_CAPSLOCK_TO_CONTROL` |`CL_CTRL`|Treat Caps Lock as Control |
|`MAGIC_UNCAPSLOCK_TO_CONTROL` |`CL_CAPS`|Stop treating Caps Lock as Control |
|`MAGIC_SWAP_LCTL_LGUI` |`LCG_SWP`|Swap Left Control and GUI |
|`MAGIC_UNSWAP_LCTL_LGUI` |`LCG_NRM`|Unswap Left Control and GUI |
|`MAGIC_SWAP_RCTL_RGUI` |`RCG_SWP`|Swap Right Control and GUI |
|`MAGIC_UNSWAP_RCTL_RGUI` |`RCG_NRM`|Unswap Right Control and GUI |
|`MAGIC_SWAP_CTL_GUI` |`CG_SWAP`|Swap Control and GUI on both sides |
|`MAGIC_UNSWAP_CTL_GUI` |`CG_NORM`|Unswap Control and GUI on both sides |
|`MAGIC_TOGGLE_CTL_GUI` |`CG_TOGG`|Toggle Control and GUI swap on both sides |
|`MAGIC_SWAP_LALT_LGUI` |`LAG_SWP`|Swap Left Alt and GUI |
|`MAGIC_UNSWAP_LALT_LGUI` |`LAG_NRM`|Unswap Left Alt and GUI |
|`MAGIC_SWAP_RALT_RGUI` |`RAG_SWP`|Swap Right Alt and GUI |
|`MAGIC_UNSWAP_RALT_RGUI` |`RAG_NRM`|Unswap Right Alt and GUI |
|`MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides |
|`MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Alt and GUI on both sides |
|`MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Alt and GUI swap on both sides |
|`MAGIC_NO_GUI` |`GUI_OFF`|Disable the GUI keys |
|`MAGIC_UNNO_GUI` |`GUI_ON` |Enable the GUI keys |
|`MAGIC_TOGGLE_GUI` |`GUI_TOG`|Toggles the status of the GUI keys |
|`MAGIC_SWAP_GRAVE_ESC` |`GE_SWAP`|Swap <code>&#96;</code> and Escape |
|`MAGIC_UNSWAP_GRAVE_ESC` |`GE_NORM`|Unswap <code>&#96;</code> and Escape |
|`MAGIC_SWAP_BACKSLASH_BACKSPACE` |`BS_SWAP`|Swap `\` and Backspace |
|`MAGIC_UNSWAP_BACKSLASH_BACKSPACE`|`BS_NORM`|Unswap `\` and Backspace |
|`MAGIC_HOST_NKRO` |`NK_ON` |Enable N-key rollover |
|`MAGIC_UNHOST_NKRO` |`NK_OFF` |Disable N-key rollover |
|`MAGIC_TOGGLE_NKRO` |`NK_TOGG`|Toggle N-key rollover |
|`MAGIC_EE_HANDS_LEFT` |`EH_LEFT`|Set the master half of a split keyboard as the left hand (for `EE_HANDS`) |
|`MAGIC_EE_HANDS_RIGHT` |`EH_RGHT`|Set the master half of a split keyboard as the right hand (for `EE_HANDS`)|
|Key |Aliases |Description |
|-------------------------------------|---------|--------------------------------------------------------------------------|
|`QK_MAGIC_SWAP_CONTROL_CAPS_LOCK` |`CL_SWAP`|Swap Caps Lock and Left Control |
|`QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK` |`CL_NORM`|Unswap Caps Lock and Left Control |
|`QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK` |`CL_TOGG`|Toggle Caps Lock and Left Control swap |
|`QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON` |`CL_CTRL`|Treat Caps Lock as Control |
|`QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF` |`CL_CAPS`|Stop treating Caps Lock as Control |
|`QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK` |`EC_SWAP`|Swap Caps Lock and Escape |
|`QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK` |`EC_NORM`|Unswap Caps Lock and Escape |
|`QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK` |`EC_TOGG`|Toggle Caps Lock and Escape swap |
|`QK_MAGIC_SWAP_LCTL_LGUI` |`CG_LSWP`|Swap Left Control and GUI |
|`QK_MAGIC_UNSWAP_LCTL_LGUI` |`CG_LNRM`|Unswap Left Control and GUI |
|`QK_MAGIC_SWAP_RCTL_RGUI` |`CG_RSWP`|Swap Right Control and GUI |
|`QK_MAGIC_UNSWAP_RCTL_RGUI` |`CG_RNRM`|Unswap Right Control and GUI |
|`QK_MAGIC_SWAP_CTL_GUI` |`CG_SWAP`|Swap Control and GUI on both sides |
|`QK_MAGIC_UNSWAP_CTL_GUI` |`CG_NORM`|Unswap Control and GUI on both sides |
|`QK_MAGIC_TOGGLE_CTL_GUI` |`CG_TOGG`|Toggle Control and GUI swap on both sides |
|`QK_MAGIC_SWAP_LALT_LGUI` |`AG_LSWP`|Swap Left Alt and GUI |
|`QK_MAGIC_UNSWAP_LALT_LGUI` |`AG_LNRM`|Unswap Left Alt and GUI |
|`QK_MAGIC_SWAP_RALT_RGUI` |`AG_RSWP`|Swap Right Alt and GUI |
|`QK_MAGIC_UNSWAP_RALT_RGUI` |`AG_RNRM`|Unswap Right Alt and GUI |
|`QK_MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides |
|`QK_MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Alt and GUI on both sides |
|`QK_MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Alt and GUI swap on both sides |
|`QK_MAGIC_GUI_OFF` |`GU_OFF` |Disable the GUI keys |
|`QK_MAGIC_GUI_ON` |`GU_ON` |Enable the GUI keys |
|`QK_MAGIC_TOGGLE_GUI` |`GU_TOGG`|Toggles the status of the GUI keys |
|`QK_MAGIC_SWAP_GRAVE_ESC` |`GE_SWAP`|Swap <code>&#96;</code> and Escape |
|`QK_MAGIC_UNSWAP_GRAVE_ESC` |`GE_NORM`|Unswap <code>&#96;</code> and Escape |
|`QK_MAGIC_SWAP_BACKSLASH_BACKSPACE` |`BS_SWAP`|Swap `\` and Backspace |
|`QK_MAGIC_UNSWAP_BACKSLASH_BACKSPACE`|`BS_NORM`|Unswap `\` and Backspace |
|`QK_MAGIC_TOGGLE_BACKSLASH_BACKSPACE`|`BS_TOGG`|Toggle `\` and Backspace swap state |
|`QK_MAGIC_NKRO_ON` |`NK_ON` |Enable N-key rollover |
|`QK_MAGIC_NKRO_OFF` |`NK_OFF` |Disable N-key rollover |
|`QK_MAGIC_TOGGLE_NKRO` |`NK_TOGG`|Toggle N-key rollover |
|`QK_MAGIC_EE_HANDS_LEFT` |`EH_LEFT`|Set the master half of a split keyboard as the left hand (for `EE_HANDS`) |
|`QK_MAGIC_EE_HANDS_RIGHT` |`EH_RGHT`|Set the master half of a split keyboard as the right hand (for `EE_HANDS`)|
## MIDI :id=midi
See also: [MIDI](feature_midi.md)
|Key |Aliases |Description |
|------------|---------|---------------------------------|
|`MI_ON` | |Turn MIDI on |
|`MI_OFF` | |Turn MIDI off |
|`MI_TOG` | |Toggle MIDI enabled |
|`MI_C` | |C octave 0 |
|`MI_Cs` |`MI_Db` |C♯/D♭ octave 0 |
|`MI_D` | |D octave 0 |
|`MI_Ds` |`MI_Eb` |D♯/E♭ octave 0 |
|`MI_E` | |E octave 0 |
|`MI_F` | |F octave 0 |
|`MI_Fs` |`MI_Gb` |F♯/G♭ octave 0 |
|`MI_G` | |G octave 0 |
|`MI_Gs` |`MI_Gs` |G♯/A♭ octave 0 |
|`MI_A` | |A octave 0 |
|`MI_As` |`MI_Bb` |A♯/B♭ octave 0 |
|`MI_B` | |B octave 0 |
|`MI_C_1` | |C octave 1 |
|`MI_Cs_1` |`MI_Db_1`|C♯/D♭ octave 1 |
|`MI_D_1` | |D octave 1 |
|`MI_Ds_1` |`MI_Eb_1`|D♯/E♭ octave 1 |
|`MI_E_1` | |E octave 1 |
|`MI_F_1` | |F octave 1 |
|`MI_Fs_1` |`MI_Gb_1`|F♯/G♭ octave 1 |
|`MI_G_1` | |G octave 1 |
|`MI_Gs_1` |`MI_Ab_1`|G♯/A♭ octave 1 |
|`MI_A_1` | |A octave 1 |
|`MI_As_1` |`MI_Bb_1`|A♯/B♭ octave 1 |
|`MI_B_1` | |B octave 1 |
|`MI_C_2` | |C octave 2 |
|`MI_Cs_2` |`MI_Db_2`|C♯/D♭ octave 2 |
|`MI_D_2` | |D octave 2 |
|`MI_Ds_2` |`MI_Eb_2`|D♯/E♭ octave 2 |
|`MI_E_2` | |E octave 2 |
|`MI_F_2` | |F octave 2 |
|`MI_Fs_2` |`MI_Gb_2`|F♯/G♭ octave 2 |
|`MI_G_2` | |G octave 2 |
|`MI_Gs_2` |`MI_Ab_2`|G♯/A♭ octave 2 |
|`MI_A_2` | |A octave 2 |
|`MI_As_2` |`MI_Bb_2`|A♯/B♭ octave 2 |
|`MI_B_2` | |B octave 2 |
|`MI_C_3` | |C octave 3 |
|`MI_Cs_3` |`MI_Db_3`|C♯/D♭ octave 3 |
|`MI_D_3` | |D octave 3 |
|`MI_Ds_3` |`MI_Eb_3`|D♯/E♭ octave 3 |
|`MI_E_3` | |E octave 3 |
|`MI_F_3` | |F octave 3 |
|`MI_Fs_3` |`MI_Gb_3`|F♯/G♭ octave 3 |
|`MI_G_3` | |G octave 3 |
|`MI_Gs_3` |`MI_Ab_3`|G♯/A♭ octave 3 |
|`MI_A_3` | |A octave 3 |
|`MI_As_3` |`MI_Bb_3`|A♯/B♭ octave 3 |
|`MI_B_3` | |B octave 3 |
|`MI_C_4` | |C octave 4 |
|`MI_Cs_4` |`MI_Db_4`|C♯/D♭ octave 4 |
|`MI_D_4` | |D octave 4 |
|`MI_Ds_4` |`MI_Eb_4`|D♯/E♭ octave 4 |
|`MI_E_4` | |E octave 4 |
|`MI_F_4` | |F octave 4 |
|`MI_Fs_4` |`MI_Gb_4`|F♯/G♭ octave 4 |
|`MI_G_4` | |G octave 4 |
|`MI_Gs_4` |`MI_Ab_4`|G♯/A♭ octave 4 |
|`MI_A_4` | |A octave 4 |
|`MI_As_4` |`MI_Bb_4`|A♯/B♭ octave 4 |
|`MI_B_4` | |B octave 4 |
|`MI_C_5` | |C octave 5 |
|`MI_Cs_5` |`MI_Db_5`|C♯/D♭ octave 5 |
|`MI_D_5` | |D octave 5 |
|`MI_Ds_5` |`MI_Eb_5`|D♯/E♭ octave 5 |
|`MI_E_5` | |E octave 5 |
|`MI_F_5` | |F octave 5 |
|`MI_Fs_5` |`MI_Gb_5`|F♯/G♭ octave 5 |
|`MI_G_5` | |G octave 5 |
|`MI_Gs_5` |`MI_Ab_5`|G♯/A♭ octave 5 |
|`MI_A_5` | |A octave 5 |
|`MI_As_5` |`MI_Bb_5`|A♯/B♭ octave 5 |
|`MI_B_5` | |B octave 5 |
|`MI_OCT_N2` | |Set octave to -2 |
|`MI_OCT_N1` | |Set octave to -1 |
|`MI_OCT_0` | |Set octave to 0 |
|`MI_OCT_1` | |Set octave to 1 |
|`MI_OCT_2` | |Set octave to 2 |
|`MI_OCT_3` | |Set octave to 3 |
|`MI_OCT_4` | |Set octave to 4 |
|`MI_OCT_5` | |Set octave to 5 |
|`MI_OCT_6` | |Set octave to 6 |
|`MI_OCT_7` | |Set octave to 7 |
|`MI_OCTD` | |Move down an octave |
|`MI_OCTU` | |Move up an octave |
|`MI_TRNS_N6`| |Set transposition to -6 semitones|
|`MI_TRNS_N5`| |Set transposition to -5 semitones|
|`MI_TRNS_N4`| |Set transposition to -4 semitones|
|`MI_TRNS_N3`| |Set transposition to -3 semitones|
|`MI_TRNS_N2`| |Set transposition to -2 semitones|
|`MI_TRNS_N1`| |Set transposition to -1 semitone |
|`MI_TRNS_0` | |No transposition |
|`MI_TRNS_1` | |Set transposition to +1 semitone |
|`MI_TRNS_2` | |Set transposition to +2 semitones|
|`MI_TRNS_3` | |Set transposition to +3 semitones|
|`MI_TRNS_4` | |Set transposition to +4 semitones|
|`MI_TRNS_5` | |Set transposition to +5 semitones|
|`MI_TRNS_6` | |Set transposition to +6 semitones|
|`MI_TRNSD` | |Decrease transposition |
|`MI_TRNSU` | |Increase transposition |
|`MI_VEL_0` | |Set velocity to 0 |
|`MI_VEL_1` | |Set velocity to 12 |
|`MI_VEL_2` | |Set velocity to 25 |
|`MI_VEL_3` | |Set velocity to 38 |
|`MI_VEL_4` | |Set velocity to 51 |
|`MI_VEL_5` | |Set velocity to 64 |
|`MI_VEL_6` | |Set velocity to 76 |
|`MI_VEL_7` | |Set velocity to 89 |
|`MI_VEL_8` | |Set velocity to 102 |
|`MI_VEL_9` | |Set velocity to 114 |
|`MI_VEL_10` | |Set velocity to 127 |
|`MI_VELD` | |Decrease velocity |
|`MI_VELU` | |Increase velocity |
|`MI_CH1` | |Set channel to 1 |
|`MI_CH2` | |Set channel to 2 |
|`MI_CH3` | |Set channel to 3 |
|`MI_CH4` | |Set channel to 4 |
|`MI_CH5` | |Set channel to 5 |
|`MI_CH6` | |Set channel to 6 |
|`MI_CH7` | |Set channel to 7 |
|`MI_CH8` | |Set channel to 8 |
|`MI_CH9` | |Set channel to 9 |
|`MI_CH10` | |Set channel to 10 |
|`MI_CH11` | |Set channel to 11 |
|`MI_CH12` | |Set channel to 12 |
|`MI_CH13` | |Set channel to 13 |
|`MI_CH14` | |Set channel to 14 |
|`MI_CH15` | |Set channel to 15 |
|`MI_CH16` | |Set channel to 16 |
|`MI_CHD` | |Decrease channel |
|`MI_CHU` | |Increase channel |
|`MI_ALLOFF` | |Stop all notes |
|`MI_SUS` | |Sustain |
|`MI_PORT` | |Portmento |
|`MI_SOST` | |Sostenuto |
|`MI_SOFT` | |Soft Pedal |
|`MI_LEG` | |Legato |
|`MI_MOD` | |Modulation |
|`MI_MODSD` | |Decrease modulation speed |
|`MI_MODSU` | |Increase modulation speed |
|`MI_BENDD` | |Bend pitch down |
|`MI_BENDU` | |Bend pitch up |
|Key |Aliases |Description |
|-------------------------------|------------------|---------------------------------|
|`QK_MIDI_ON` |`MI_ON` |Turn MIDI on |
|`QK_MIDI_OFF` |`MI_OFF` |Turn MIDI off |
|`QK_MIDI_TOGGLE` |`MI_TOGG` |Toggle MIDI enabled |
|`QK_MIDI_NOTE_C_0` |`MI_C` |C octave 0 |
|`QK_MIDI_NOTE_C_SHARP_0` |`MI_Cs`, `MI_Db` |C♯/D♭ octave 0 |
|`QK_MIDI_NOTE_D_0` |`MI_D` |D octave 0 |
|`QK_MIDI_NOTE_D_SHARP_0` |`MI_Ds`, `MI_Eb` |D♯/E♭ octave 0 |
|`QK_MIDI_NOTE_E_0` |`MI_E` |E octave 0 |
|`QK_MIDI_NOTE_F_0` |`MI_F` |F octave 0 |
|`QK_MIDI_NOTE_F_SHARP_0` |`MI_Fs`, `MI_Gb` |F♯/G♭ octave 0 |
|`QK_MIDI_NOTE_G_0` |`MI_G` |G octave 0 |
|`QK_MIDI_NOTE_G_SHARP_0` |`MI_Gs`, `MI_Ab` |G♯/A♭ octave 0 |
|`QK_MIDI_NOTE_A_0` |`MI_A` |A octave 0 |
|`QK_MIDI_NOTE_A_SHARP_0` |`MI_As`, `MI_Bb` |A♯/B♭ octave 0 |
|`QK_MIDI_NOTE_B_0` |`MI_B` |B octave 0 |
|`QK_MIDI_NOTE_C_1` |`MI_C1` |C octave 1 |
|`QK_MIDI_NOTE_C_SHARP_1` |`MI_Cs1`, `MI_Db1`|C♯/D♭ octave 1 |
|`QK_MIDI_NOTE_D_1` |`MI_D1` |D octave 1 |
|`QK_MIDI_NOTE_D_SHARP_1` |`MI_Ds1`, `MI_Eb1`|D♯/E♭ octave 1 |
|`QK_MIDI_NOTE_E_1` |`MI_E1` |E octave 1 |
|`QK_MIDI_NOTE_F_1` |`MI_F1` |F octave 1 |
|`QK_MIDI_NOTE_F_SHARP_1` |`MI_Fs1`, `MI_Gb1`|F♯/G♭ octave 1 |
|`QK_MIDI_NOTE_G_1` |`MI_G1` |G octave 1 |
|`QK_MIDI_NOTE_G_SHARP_1` |`MI_Gs1`, `MI_Ab1`|G♯/A♭ octave 1 |
|`QK_MIDI_NOTE_A_1` |`MI_A1` |A octave 1 |
|`QK_MIDI_NOTE_A_SHARP_1` |`MI_As1`, `MI_Bb1`|A♯/B♭ octave 1 |
|`QK_MIDI_NOTE_B_1` |`MI_B1` |B octave 1 |
|`QK_MIDI_NOTE_C_2` |`MI_C2` |C octave 2 |
|`QK_MIDI_NOTE_C_SHARP_2` |`MI_Cs2`, `MI_Db2`|C♯/D♭ octave 2 |
|`QK_MIDI_NOTE_D_2` |`MI_D2` |D octave 2 |
|`QK_MIDI_NOTE_D_SHARP_2` |`MI_Ds2`, `MI_Eb2`|D♯/E♭ octave 2 |
|`QK_MIDI_NOTE_E_2` |`MI_E2` |E octave 2 |
|`QK_MIDI_NOTE_F_2` |`MI_F2` |F octave 2 |
|`QK_MIDI_NOTE_F_SHARP_2` |`MI_Fs2`, `MI_Gb2`|F♯/G♭ octave 2 |
|`QK_MIDI_NOTE_G_2` |`MI_G2` |G octave 2 |
|`QK_MIDI_NOTE_G_SHARP_2` |`MI_Gs2`, `MI_Ab2`|G♯/A♭ octave 2 |
|`QK_MIDI_NOTE_A_2` |`MI_A2` |A octave 2 |
|`QK_MIDI_NOTE_A_SHARP_2` |`MI_As2`, `MI_Bb2`|A♯/B♭ octave 2 |
|`QK_MIDI_NOTE_B_2` |`MI_B2` |B octave 2 |
|`QK_MIDI_NOTE_C_3` |`MI_C3` |C octave 3 |
|`QK_MIDI_NOTE_C_SHARP_3` |`MI_Cs3`, `MI_Db3`|C♯/D♭ octave 3 |
|`QK_MIDI_NOTE_D_3` |`MI_D3` |D octave 3 |
|`QK_MIDI_NOTE_D_SHARP_3` |`MI_Ds3`, `MI_Eb3`|D♯/E♭ octave 3 |
|`QK_MIDI_NOTE_E_3` |`MI_E3` |E octave 3 |
|`QK_MIDI_NOTE_F_3` |`MI_F3` |F octave 3 |
|`QK_MIDI_NOTE_F_SHARP_3` |`MI_Fs3`, `MI_Gb3`|F♯/G♭ octave 3 |
|`QK_MIDI_NOTE_G_3` |`MI_G3` |G octave 3 |
|`QK_MIDI_NOTE_G_SHARP_3` |`MI_Gs3`, `MI_Ab3`|G♯/A♭ octave 3 |
|`QK_MIDI_NOTE_A_3` |`MI_A3` |A octave 3 |
|`QK_MIDI_NOTE_A_SHARP_3` |`MI_As3`, `MI_Bb3`|A♯/B♭ octave 3 |
|`QK_MIDI_NOTE_B_3` |`MI_B3` |B octave 3 |
|`QK_MIDI_NOTE_C_4` |`MI_C4` |C octave 4 |
|`QK_MIDI_NOTE_C_SHARP_4` |`MI_Cs4`, `MI_Db4`|C♯/D♭ octave 4 |
|`QK_MIDI_NOTE_D_4` |`MI_D4` |D octave 4 |
|`QK_MIDI_NOTE_D_SHARP_4` |`MI_Ds4`, `MI_Eb4`|D♯/E♭ octave 4 |
|`QK_MIDI_NOTE_E_4` |`MI_E4` |E octave 4 |
|`QK_MIDI_NOTE_F_4` |`MI_F4` |F octave 4 |
|`QK_MIDI_NOTE_F_SHARP_4` |`MI_Fs4`, `MI_Gb4`|F♯/G♭ octave 4 |
|`QK_MIDI_NOTE_G_4` |`MI_G4` |G octave 4 |
|`QK_MIDI_NOTE_G_SHARP_4` |`MI_Gs4`, `MI_Ab4`|G♯/A♭ octave 4 |
|`QK_MIDI_NOTE_A_4` |`MI_A4` |A octave 4 |
|`QK_MIDI_NOTE_A_SHARP_4` |`MI_As4`, `MI_Bb4`|A♯/B♭ octave 4 |
|`QK_MIDI_NOTE_B_4` |`MI_B4` |B octave 4 |
|`QK_MIDI_NOTE_C_5` |`MI_C5` |C octave 5 |
|`QK_MIDI_NOTE_C_SHARP_5` |`MI_Cs5`, `MI_Db5`|C♯/D♭ octave 5 |
|`QK_MIDI_NOTE_D_5` |`MI_D5` |D octave 5 |
|`QK_MIDI_NOTE_D_SHARP_5` |`MI_Ds5`, `MI_Eb5`|D♯/E♭ octave 5 |
|`QK_MIDI_NOTE_E_5` |`MI_E5` |E octave 5 |
|`QK_MIDI_NOTE_F_5` |`MI_F5` |F octave 5 |
|`QK_MIDI_NOTE_F_SHARP_5` |`MI_Fs5`, `MI_Gb5`|F♯/G♭ octave 5 |
|`QK_MIDI_NOTE_G_5` |`MI_G5` |G octave 5 |
|`QK_MIDI_NOTE_G_SHARP_5` |`MI_Gs5`, `MI_Ab5`|G♯/A♭ octave 5 |
|`QK_MIDI_NOTE_A_5` |`MI_A5` |A octave 5 |
|`QK_MIDI_NOTE_A_SHARP_5` |`MI_As5`, `MI_Bb5`|A♯/B♭ octave 5 |
|`QK_MIDI_NOTE_B_5` |`MI_B5` |B octave 5 |
|`QK_MIDI_OCTAVE_N2` |`MI_OCN2` |Set octave to -2 |
|`QK_MIDI_OCTAVE_N1` |`MI_OCN1` |Set octave to -1 |
|`QK_MIDI_OCTAVE_0` |`MI_OC0` |Set octave to 0 |
|`QK_MIDI_OCTAVE_1` |`MI_OC1` |Set octave to 1 |
|`QK_MIDI_OCTAVE_2` |`MI_OC2` |Set octave to 2 |
|`QK_MIDI_OCTAVE_3` |`MI_OC3` |Set octave to 3 |
|`QK_MIDI_OCTAVE_4` |`MI_OC4` |Set octave to 4 |
|`QK_MIDI_OCTAVE_5` |`MI_OC5` |Set octave to 5 |
|`QK_MIDI_OCTAVE_6` |`MI_OC6` |Set octave to 6 |
|`QK_MIDI_OCTAVE_7` |`MI_OC7` |Set octave to 7 |
|`QK_MIDI_OCTAVE_DOWN` |`MI_OCTD` |Move down an octave |
|`QK_MIDI_OCTAVE_UP` |`MI_OCTU` |Move up an octave |
|`QK_MIDI_TRANSPOSE_N6` |`MI_TRN6` |Set transposition to -6 semitones|
|`QK_MIDI_TRANSPOSE_N5` |`MI_TRN5` |Set transposition to -5 semitones|
|`QK_MIDI_TRANSPOSE_N4` |`MI_TRN4` |Set transposition to -4 semitones|
|`QK_MIDI_TRANSPOSE_N3` |`MI_TRN3` |Set transposition to -3 semitones|
|`QK_MIDI_TRANSPOSE_N2` |`MI_TRN2` |Set transposition to -2 semitones|
|`QK_MIDI_TRANSPOSE_N1` |`MI_TRN1` |Set transposition to -1 semitone |
|`QK_MIDI_TRANSPOSE_0` |`MI_TR0` |No transposition |
|`QK_MIDI_TRANSPOSE_1` |`MI_TR1` |Set transposition to +1 semitone |
|`QK_MIDI_TRANSPOSE_2` |`MI_TR2` |Set transposition to +2 semitones|
|`QK_MIDI_TRANSPOSE_3` |`MI_TR3` |Set transposition to +3 semitones|
|`QK_MIDI_TRANSPOSE_4` |`MI_TR4` |Set transposition to +4 semitones|
|`QK_MIDI_TRANSPOSE_5` |`MI_TR5` |Set transposition to +5 semitones|
|`QK_MIDI_TRANSPOSE_6` |`MI_TR6` |Set transposition to +6 semitones|
|`QK_MIDI_TRANSPOSE_DOWN` |`MI_TRSD` |Decrease transposition |
|`QK_MIDI_TRANSPOSE_UP` |`MI_TRSU` |Increase transposition |
|`QK_MIDI_VELOCITY_0` |`MI_VL0` |Set velocity to 0 |
|`QK_MIDI_VELOCITY_1` |`MI_VL1` |Set velocity to 12 |
|`QK_MIDI_VELOCITY_2` |`MI_VL2` |Set velocity to 25 |
|`QK_MIDI_VELOCITY_3` |`MI_VL3` |Set velocity to 38 |
|`QK_MIDI_VELOCITY_4` |`MI_VL4` |Set velocity to 51 |
|`QK_MIDI_VELOCITY_5` |`MI_VL5` |Set velocity to 64 |
|`QK_MIDI_VELOCITY_6` |`MI_VL6` |Set velocity to 76 |
|`QK_MIDI_VELOCITY_7` |`MI_VL7` |Set velocity to 89 |
|`QK_MIDI_VELOCITY_8` |`MI_VL8` |Set velocity to 102 |
|`QK_MIDI_VELOCITY_9` |`MI_VL9` |Set velocity to 114 |
|`QK_MIDI_VELOCITY_10` |`MI_VL10` |Set velocity to 127 |
|`QK_MIDI_VELOCITY_DOWN` |`MI_VELD` |Decrease velocity |
|`QK_MIDI_VELOCITY_UP` |`MI_VELU` |Increase velocity |
|`QK_MIDI_CHANNEL_1` |`MI_CH1` |Set channel to 1 |
|`QK_MIDI_CHANNEL_2` |`MI_CH2` |Set channel to 2 |
|`QK_MIDI_CHANNEL_3` |`MI_CH3` |Set channel to 3 |
|`QK_MIDI_CHANNEL_4` |`MI_CH4` |Set channel to 4 |
|`QK_MIDI_CHANNEL_5` |`MI_CH5` |Set channel to 5 |
|`QK_MIDI_CHANNEL_6` |`MI_CH6` |Set channel to 6 |
|`QK_MIDI_CHANNEL_7` |`MI_CH7` |Set channel to 7 |
|`QK_MIDI_CHANNEL_8` |`MI_CH8` |Set channel to 8 |
|`QK_MIDI_CHANNEL_9` |`MI_CH9` |Set channel to 9 |
|`QK_MIDI_CHANNEL_10` |`MI_CH10` |Set channel to 10 |
|`QK_MIDI_CHANNEL_11` |`MI_CH11` |Set channel to 11 |
|`QK_MIDI_CHANNEL_12` |`MI_CH12` |Set channel to 12 |
|`QK_MIDI_CHANNEL_13` |`MI_CH13` |Set channel to 13 |
|`QK_MIDI_CHANNEL_14` |`MI_CH14` |Set channel to 14 |
|`QK_MIDI_CHANNEL_15` |`MI_CH15` |Set channel to 15 |
|`QK_MIDI_CHANNEL_16` |`MI_CH16` |Set channel to 16 |
|`QK_MIDI_CHANNEL_DOWN` |`MI_CHND` |Decrease channel |
|`QK_MIDI_CHANNEL_UP` |`MI_CHNU` |Increase channel |
|`QK_MIDI_ALL_NOTES_OFF` |`MI_AOFF` |Stop all notes |
|`QK_MIDI_SUSTAIN` |`MI_SUST` |Sustain |
|`QK_MIDI_PORTAMENTO` |`MI_PORT` |Portmento |
|`QK_MIDI_SOSTENUTO` |`MI_SOST` |Sostenuto |
|`QK_MIDI_SOFT` |`MI_SOFT` |Soft Pedal |
|`QK_MIDI_LEGATO` |`MI_LEG` |Legato |
|`QK_MIDI_MODULATION` |`MI_MOD` |Modulation |
|`QK_MIDI_MODULATION_SPEED_DOWN`|`MI_MODD` |Decrease modulation speed |
|`QK_MIDI_MODULATION_SPEED_UP` |`MI_MODU` |Increase modulation speed |
|`QK_MIDI_PITCH_BEND_DOWN` |`MI_BNDD` |Bend pitch down |
|`QK_MIDI_PITCH_BEND_UP` |`MI_BNDU` |Bend pitch up |
## Mouse Keys :id=mouse-keys
@ -556,7 +627,7 @@ See also: [Modifier Keys](feature_advanced_keycodes.md#modifier-keys)
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|`RALT(kc)`|`ROPT(kc)`, `ALGR(kc)` |Hold Right Alt (AltGr) and press `kc` |
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|`RGUI(kc)`|`RCMD(kc)`, `RWIN(kc)` |Hold Right GUI and press `kc` |
|`LSG(kc)` |`SGUI(kc)`, `SCMD(kc)`, `SWIN(kc)`|Hold Left Shift and Left GUI and press `kc` |
|`LAG(kc)` | |Hold Left Alt and Left GUI and press `kc` |
|`RSG(kc)` | |Hold Right Shift and Right GUI and press `kc` |
@ -604,11 +675,11 @@ See also: [Mod-Tap](mod_tap.md)
See also: [Dynamic Tapping Term](tap_hold#dynamic-tapping-term)
| Key | Description |
|-------------|------------------------------------------------------------------------------------------------------------------------|
| `DT_PRNT` | "Dynamic Tapping Term Print": Types the current tapping term, in milliseconds |
| `DT_UP` | "Dynamic Tapping Term Up": Increases the current tapping term by `DYNAMIC_TAPPING_TERM_INCREMENT`ms (5ms by default) |
| `DT_DOWN` | "Dynamic Tapping Term Down": Decreases the current tapping term by `DYNAMIC_TAPPING_TERM_INCREMENT`ms (5ms by default) |
| Key | Aliases | Description |
|-------------------------------|---------|-------------------------------------------------------------------------------------------|
|`QK_DYNAMIC_TAPPING_TERM_PRINT`|`DT_PRNT`| Types the current tapping term, in milliseconds |
|`QK_DYNAMIC_TAPPING_TERM_UP` |`DT_UP` | Increases the current tapping term by `DYNAMIC_TAPPING_TERM_INCREMENT`ms (5ms by default) |
|`QK_DYNAMIC_TAPPING_TERM_DOWN` |`DT_DOWN`| Decreases the current tapping term by `DYNAMIC_TAPPING_TERM_INCREMENT`ms (5ms by default) |
## RGB Lighting :id=rgb-lighting
@ -653,15 +724,6 @@ See also: [RGB Matrix Lighting](feature_rgb_matrix.md)
|`RGB_SPI` | |Increase effect speed (does not support eeprom yet), decrease speed when Shift is held|
|`RGB_SPD` | |Decrease effect speed (does not support eeprom yet), increase speed when Shift is held|
## Thermal Printer :id=thermal-printer
See also: [Thermal Printer](feature_thermal_printer.md)
|Key |Description |
|-----------|----------------------------------------|
|`PRINT_ON` |Start printing everything the user types|
|`PRINT_OFF`|Stop printing everything the user types |
## US ANSI Shifted Symbols :id=us-ansi-shifted-symbols
See also: [US ANSI Shifted Symbols](keycodes_us_ansi_shifted.md)
@ -694,96 +756,96 @@ See also: [US ANSI Shifted Symbols](keycodes_us_ansi_shifted.md)
See also: [One Shot Keys](one_shot_keys.md)
|Key |Description |
|------------|----------------------------------|
|`OSM(mod)` |Hold `mod` for one keypress |
|`OSL(layer)`|Switch to `layer` for one keypress|
|`OS_ON` |Turns One Shot keys on |
|`OS_OFF` |Turns One Shot keys off |
|`OS_TOGG` |Toggles One Shot keys status |
|Key |Aliases |Description |
|--------------------|---------|----------------------------------|
|`OSM(mod)` | |Hold `mod` for one keypress |
|`OSL(layer)` | |Switch to `layer` for one keypress|
|`QK_ONE_SHOT_TOGGLE`|`OS_TOGG`|Toggles One Shot keys status |
|`QK_ONE_SHOT_ON` |`OS_ON` |Turns One Shot keys on |
|`QK_ONE_SHOT_OFF` |`OS_OFF` |Turns One Shot keys off |
## Programmable Button Support :id=programmable-button
See also: [Programmable Button](feature_programmable_button.md)
|Key |Description |
|------------------------|----------------------|
|`PROGRAMMABLE_BUTTON_1` |Programmable button 1 |
|`PROGRAMMABLE_BUTTON_2` |Programmable button 2 |
|`PROGRAMMABLE_BUTTON_3` |Programmable button 3 |
|`PROGRAMMABLE_BUTTON_4` |Programmable button 4 |
|`PROGRAMMABLE_BUTTON_5` |Programmable button 5 |
|`PROGRAMMABLE_BUTTON_6` |Programmable button 6 |
|`PROGRAMMABLE_BUTTON_7` |Programmable button 7 |
|`PROGRAMMABLE_BUTTON_8` |Programmable button 8 |
|`PROGRAMMABLE_BUTTON_9` |Programmable button 9 |
|`PROGRAMMABLE_BUTTON_10`|Programmable button 10|
|`PROGRAMMABLE_BUTTON_11`|Programmable button 11|
|`PROGRAMMABLE_BUTTON_12`|Programmable button 12|
|`PROGRAMMABLE_BUTTON_13`|Programmable button 13|
|`PROGRAMMABLE_BUTTON_14`|Programmable button 14|
|`PROGRAMMABLE_BUTTON_15`|Programmable button 15|
|`PROGRAMMABLE_BUTTON_16`|Programmable button 16|
|`PROGRAMMABLE_BUTTON_17`|Programmable button 17|
|`PROGRAMMABLE_BUTTON_18`|Programmable button 18|
|`PROGRAMMABLE_BUTTON_19`|Programmable button 19|
|`PROGRAMMABLE_BUTTON_20`|Programmable button 20|
|`PROGRAMMABLE_BUTTON_21`|Programmable button 21|
|`PROGRAMMABLE_BUTTON_22`|Programmable button 22|
|`PROGRAMMABLE_BUTTON_23`|Programmable button 23|
|`PROGRAMMABLE_BUTTON_24`|Programmable button 24|
|`PROGRAMMABLE_BUTTON_25`|Programmable button 25|
|`PROGRAMMABLE_BUTTON_26`|Programmable button 26|
|`PROGRAMMABLE_BUTTON_27`|Programmable button 27|
|`PROGRAMMABLE_BUTTON_28`|Programmable button 28|
|`PROGRAMMABLE_BUTTON_29`|Programmable button 29|
|`PROGRAMMABLE_BUTTON_30`|Programmable button 30|
|`PROGRAMMABLE_BUTTON_31`|Programmable button 31|
|`PROGRAMMABLE_BUTTON_32`|Programmable button 32|
|`PB_1` to `PB_32` |Aliases for keymaps |
|Key |Aliases|Description |
|---------------------------|-------|----------------------|
|`QK_PROGRAMMABLE_BUTTON_1` |`PB_1` |Programmable button 1 |
|`QK_PROGRAMMABLE_BUTTON_2` |`PB_2` |Programmable button 2 |
|`QK_PROGRAMMABLE_BUTTON_3` |`PB_3` |Programmable button 3 |
|`QK_PROGRAMMABLE_BUTTON_4` |`PB_4` |Programmable button 4 |
|`QK_PROGRAMMABLE_BUTTON_5` |`PB_5` |Programmable button 5 |
|`QK_PROGRAMMABLE_BUTTON_6` |`PB_6` |Programmable button 6 |
|`QK_PROGRAMMABLE_BUTTON_7` |`PB_7` |Programmable button 7 |
|`QK_PROGRAMMABLE_BUTTON_8` |`PB_8` |Programmable button 8 |
|`QK_PROGRAMMABLE_BUTTON_9` |`PB_9` |Programmable button 9 |
|`QK_PROGRAMMABLE_BUTTON_10`|`PB_10`|Programmable button 10|
|`QK_PROGRAMMABLE_BUTTON_11`|`PB_11`|Programmable button 11|
|`QK_PROGRAMMABLE_BUTTON_12`|`PB_12`|Programmable button 12|
|`QK_PROGRAMMABLE_BUTTON_13`|`PB_13`|Programmable button 13|
|`QK_PROGRAMMABLE_BUTTON_14`|`PB_14`|Programmable button 14|
|`QK_PROGRAMMABLE_BUTTON_15`|`PB_15`|Programmable button 15|
|`QK_PROGRAMMABLE_BUTTON_16`|`PB_16`|Programmable button 16|
|`QK_PROGRAMMABLE_BUTTON_17`|`PB_17`|Programmable button 17|
|`QK_PROGRAMMABLE_BUTTON_18`|`PB_18`|Programmable button 18|
|`QK_PROGRAMMABLE_BUTTON_19`|`PB_19`|Programmable button 19|
|`QK_PROGRAMMABLE_BUTTON_20`|`PB_20`|Programmable button 20|
|`QK_PROGRAMMABLE_BUTTON_21`|`PB_21`|Programmable button 21|
|`QK_PROGRAMMABLE_BUTTON_22`|`PB_22`|Programmable button 22|
|`QK_PROGRAMMABLE_BUTTON_23`|`PB_23`|Programmable button 23|
|`QK_PROGRAMMABLE_BUTTON_24`|`PB_24`|Programmable button 24|
|`QK_PROGRAMMABLE_BUTTON_25`|`PB_25`|Programmable button 25|
|`QK_PROGRAMMABLE_BUTTON_26`|`PB_26`|Programmable button 26|
|`QK_PROGRAMMABLE_BUTTON_27`|`PB_27`|Programmable button 27|
|`QK_PROGRAMMABLE_BUTTON_28`|`PB_28`|Programmable button 28|
|`QK_PROGRAMMABLE_BUTTON_29`|`PB_29`|Programmable button 29|
|`QK_PROGRAMMABLE_BUTTON_30`|`PB_30`|Programmable button 30|
|`QK_PROGRAMMABLE_BUTTON_31`|`PB_31`|Programmable button 31|
|`QK_PROGRAMMABLE_BUTTON_32`|`PB_32`|Programmable button 32|
## Space Cadet :id=space-cadet
See also: [Space Cadet](feature_space_cadet.md)
|Key |Description |
|-----------|----------------------------------------|
|`KC_LCPO` |Left Control when held, `(` when tapped |
|`KC_RCPC` |Right Control when held, `)` when tapped|
|`KC_LSPO` |Left Shift when held, `(` when tapped |
|`KC_RSPC` |Right Shift when held, `)` when tapped |
|`KC_LAPO` |Left Alt when held, `(` when tapped |
|`KC_RAPC` |Right Alt when held, `)` when tapped |
|`KC_SFTENT`|Right Shift when held, Enter when tapped|
|Key |Aliases |Description |
|----------------------------------------------|---------|----------------------------------------|
|`QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN` |`SC_LCPO`|Left Control when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE` |`SC_RCPC`|Right Control when held, `)` when tapped|
|`QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN` |`SC_LSPO`|Left Shift when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE`|`SC_RSPC`|Right Shift when held, `)` when tapped |
|`QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN` |`SC_LAPO`|Left Alt when held, `(` when tapped |
|`QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE` |`SC_RAPC`|Right Alt when held, `)` when tapped |
|`QK_SPACE_CADET_RIGHT_SHIFT_ENTER` |`SC_SENT`|Right Shift when held, Enter when tapped|
## Swap Hands :id=swap-hands
See also: [Swap Hands](feature_swap_hands.md)
|Key |Description |
|-----------|-------------------------------------------------------------------------|
|`SH_T(key)`|Sends `key` with a tap; momentary swap when held. |
|`SW_ON` |Turns on swapping and leaves it on. |
|`SW_OFF` |Turn off swapping and leaves it off. Good for returning to a known state.|
|`SH_MON` |Swaps hands when pressed, returns to normal when released (momentary). |
|`SH_MOFF` |Momentarily turns off swap. |
|`SH_TG` |Toggles swap on and off with every key press. |
|`SH_TT` |Toggles with a tap; momentary when held. |
|`SH_OS` |One shot swap hands: toggle while pressed or until next key press. |
|Key |Aliases |Description |
|-----------------------------|---------|----------------------------------------------------|
|`SH_T(kc)` | |Momentary swap when held, `kc` when tapped |
|`QK_SWAP_HANDS_ON` |`SH_ON` |Turn on hand swap |
|`QK_SWAP_HANDS_OFF` |`SH_OFF` |Turn off hand swap |
|`QK_SWAP_HANDS_MOMENTARY_ON` |`SH_MON` |Turn on hand swap while held |
|`QK_SWAP_HANDS_MOMENTARY_OFF`|`SH_MOFF`|Turn off hand swap while held |
|`QK_SWAP_HANDS_TOGGLE` |`SH_TOGG`|Toggle hand swap |
|`QK_SWAP_HANDS_TAP_TOGGLE` |`SH_TT` |Momentary swap when held, toggle when tapped |
|`QK_SWAP_HANDS_ONE_SHOT` |`SH_OS` |Turn on hand swap while held or until next key press|
## Unicode Support :id=unicode-support
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|
|`UNICODE_MODE_FORWARD`|`UC_MOD` |Cycle through selected input modes |
|`UNICODE_MODE_REVERSE`|`UC_RMOD`|Cycle through selected input modes in reverse |
|`UNICODE_MODE_MAC` |`UC_M_MA`|Switch to macOS input |
|`UNICODE_MODE_LNX` |`UC_M_LN`|Switch to Linux input |
|`UNICODE_MODE_WIN` |`UC_M_WI`|Switch to Windows input |
|`UNICODE_MODE_BSD` |`UC_M_BS`|Switch to BSD input (not implemented) |
|`UNICODE_MODE_WINC` |`UC_M_WC`|Switch to Windows input using WinCompose |
|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|
|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Cycle through selected input modes |
|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Cycle through selected input modes in reverse |
|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |Switch to macOS input |
|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|Switch to Linux input |
|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |Switch to Windows input |
|`QK_UNICODE_MODE_BSD` |`UC_BSD` |Switch to BSD input (not implemented) |
|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|Switch to Windows input using WinCompose |
|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|Switch to emacs (`C-x-8 RET`) |

View file

@ -193,34 +193,38 @@ These keycodes are not part of the Keyboard/Keypad usage page. The `SYSTEM_` key
?> Some of these keycodes may behave differently depending on the OS. For example, on macOS, the keycodes `KC_MEDIA_FAST_FORWARD`, `KC_MEDIA_REWIND`, `KC_MEDIA_NEXT_TRACK` and `KC_MEDIA_PREV_TRACK` skip within the current track when held, but skip the entire track when tapped.
|Key |Aliases |Description |
|-----------------------|---------|-------------------|
|`KC_SYSTEM_POWER` |`KC_PWR` |System Power Down |
|`KC_SYSTEM_SLEEP` |`KC_SLEP`|System Sleep |
|`KC_SYSTEM_WAKE` |`KC_WAKE`|System Wake |
|`KC_AUDIO_MUTE` |`KC_MUTE`|Mute |
|`KC_AUDIO_VOL_UP` |`KC_VOLU`|Volume Up |
|`KC_AUDIO_VOL_DOWN` |`KC_VOLD`|Volume Down |
|`KC_MEDIA_NEXT_TRACK` |`KC_MNXT`|Next Track |
|`KC_MEDIA_PREV_TRACK` |`KC_MPRV`|Previous Track |
|`KC_MEDIA_STOP` |`KC_MSTP`|Stop Track |
|`KC_MEDIA_PLAY_PAUSE` |`KC_MPLY`|Play/Pause Track |
|`KC_MEDIA_SELECT` |`KC_MSEL`|Launch Media Player|
|`KC_MEDIA_EJECT` |`KC_EJCT`|Eject |
|`KC_MAIL` | |Launch Mail |
|`KC_CALCULATOR` |`KC_CALC`|Launch Calculator |
|`KC_MY_COMPUTER` |`KC_MYCM`|Launch My Computer |
|`KC_WWW_SEARCH` |`KC_WSCH`|Browser Search |
|`KC_WWW_HOME` |`KC_WHOM`|Browser Home |
|`KC_WWW_BACK` |`KC_WBAK`|Browser Back |
|`KC_WWW_FORWARD` |`KC_WFWD`|Browser Forward |
|`KC_WWW_STOP` |`KC_WSTP`|Browser Stop |
|`KC_WWW_REFRESH` |`KC_WREF`|Browser Refresh |
|`KC_WWW_FAVORITES` |`KC_WFAV`|Browser Favorites |
|`KC_MEDIA_FAST_FORWARD`|`KC_MFFD`|Next Track |
|`KC_MEDIA_REWIND` |`KC_MRWD`|Previous Track |
|`KC_BRIGHTNESS_UP` |`KC_BRIU`|Brightness Up |
|`KC_BRIGHTNESS_DOWN` |`KC_BRID`|Brightness Down |
|Key |Aliases |Description |
|-----------------------|---------|--------------------|
|`KC_SYSTEM_POWER` |`KC_PWR` |System Power Down |
|`KC_SYSTEM_SLEEP` |`KC_SLEP`|System Sleep |
|`KC_SYSTEM_WAKE` |`KC_WAKE`|System Wake |
|`KC_AUDIO_MUTE` |`KC_MUTE`|Mute |
|`KC_AUDIO_VOL_UP` |`KC_VOLU`|Volume Up |
|`KC_AUDIO_VOL_DOWN` |`KC_VOLD`|Volume Down |
|`KC_MEDIA_NEXT_TRACK` |`KC_MNXT`|Next Track |
|`KC_MEDIA_PREV_TRACK` |`KC_MPRV`|Previous Track |
|`KC_MEDIA_STOP` |`KC_MSTP`|Stop Track |
|`KC_MEDIA_PLAY_PAUSE` |`KC_MPLY`|Play/Pause Track |
|`KC_MEDIA_SELECT` |`KC_MSEL`|Launch Media Player |
|`KC_MEDIA_EJECT` |`KC_EJCT`|Eject |
|`KC_MAIL` | |Launch Mail |
|`KC_CALCULATOR` |`KC_CALC`|Launch Calculator |
|`KC_MY_COMPUTER` |`KC_MYCM`|Launch My Computer |
|`KC_WWW_SEARCH` |`KC_WSCH`|Browser Search |
|`KC_WWW_HOME` |`KC_WHOM`|Browser Home |
|`KC_WWW_BACK` |`KC_WBAK`|Browser Back |
|`KC_WWW_FORWARD` |`KC_WFWD`|Browser Forward |
|`KC_WWW_STOP` |`KC_WSTP`|Browser Stop |
|`KC_WWW_REFRESH` |`KC_WREF`|Browser Refresh |
|`KC_WWW_FAVORITES` |`KC_WFAV`|Browser Favorites |
|`KC_MEDIA_FAST_FORWARD`|`KC_MFFD`|Next Track |
|`KC_MEDIA_REWIND` |`KC_MRWD`|Previous Track |
|`KC_BRIGHTNESS_UP` |`KC_BRIU`|Brightness Up |
|`KC_BRIGHTNESS_DOWN` |`KC_BRID`|Brightness Down |
|`KC_CONTROL_PANEL` |`KC_CPNL`|Open Control Panel |
|`KC_ASSISTANT` |`KC_ASST`|Launch Assistant |
|`KC_MISSION_CONTROL` |`KC_MCTL`|Open Mission Control|
|`KC_LAUNCHPAD` |`KC_LPAD`|Open Launchpad |
## Number Pad

View file

@ -2,39 +2,40 @@
**Magic Keycodes** are prefixed with `MAGIC_`, and allow you to access the functionality of the deprecated Bootmagic feature *after* your keyboard has initialized. To use the keycodes, assign them to your keymap as you would any other keycode.
|Key |Aliases |Description |
|----------------------------------|---------|--------------------------------------------------------------------------|
|`MAGIC_SWAP_CONTROL_CAPSLOCK` |`CL_SWAP`|Swap Caps Lock and Left Control |
|`MAGIC_UNSWAP_CONTROL_CAPSLOCK` |`CL_NORM`|Unswap Caps Lock and Left Control |
|`MAGIC_TOGGLE_CONTROL_CAPSLOCK` |`CL_TOGG`|Toggle Caps Lock and Left Control swap |
|`MAGIC_SWAP_ESCAPE_CAPSLOCK` |`EC_SWAP`|Swap Caps Lock and Escape |
|`MAGIC_UNSWAP_ESCAPE_CAPSLOCK` |`EC_NORM`|Unswap Caps Lock and Escape |
|`MAGIC_TOGGLE_ESCAPE_CAPSLOCK` |`EC_TOGG`|Toggle Caps Lock and Escape swap |
|`MAGIC_CAPSLOCK_TO_CONTROL` |`CL_CTRL`|Treat Caps Lock as Control |
|`MAGIC_UNCAPSLOCK_TO_CONTROL` |`CL_CAPS`|Stop treating Caps Lock as Control |
|`MAGIC_SWAP_LCTL_LGUI` |`LCG_SWP`|Swap Left Control and GUI |
|`MAGIC_UNSWAP_LCTL_LGUI` |`LCG_NRM`|Unswap Left Control and GUI |
|`MAGIC_SWAP_RCTL_RGUI` |`RCG_SWP`|Swap Right Control and GUI |
|`MAGIC_UNSWAP_RCTL_RGUI` |`RCG_NRM`|Unswap Right Control and GUI |
|`MAGIC_SWAP_CTL_GUI` |`CG_SWAP`|Swap Control and GUI on both sides |
|`MAGIC_UNSWAP_CTL_GUI` |`CG_NORM`|Unswap Control and GUI on both sides |
|`MAGIC_TOGGLE_CTL_GUI` |`CG_TOGG`|Toggle Control and GUI swap on both sides |
|`MAGIC_SWAP_LALT_LGUI` |`LAG_SWP`|Swap Left Alt and GUI |
|`MAGIC_UNSWAP_LALT_LGUI` |`LAG_NRM`|Unswap Left Alt and GUI |
|`MAGIC_SWAP_RALT_RGUI` |`RAG_SWP`|Swap Right Alt and GUI |
|`MAGIC_UNSWAP_RALT_RGUI` |`RAG_NRM`|Unswap Right Alt and GUI |
|`MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides |
|`MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Alt and GUI on both sides |
|`MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Alt and GUI swap on both sides |
|`MAGIC_NO_GUI` |`GUI_OFF`|Disable the GUI keys |
|`MAGIC_UNNO_GUI` |`GUI_ON` |Enable the GUI keys |
|`MAGIC_TOGGLE_GUI` |`GUI_TOG`|Toggles the status of the GUI keys |
|`MAGIC_SWAP_GRAVE_ESC` |`GE_SWAP`|Swap <code>&#96;</code> and Escape |
|`MAGIC_UNSWAP_GRAVE_ESC` |`GE_NORM`|Unswap <code>&#96;</code> and Escape |
|`MAGIC_SWAP_BACKSLASH_BACKSPACE` |`BS_SWAP`|Swap `\` and Backspace |
|`MAGIC_UNSWAP_BACKSLASH_BACKSPACE`|`BS_NORM`|Unswap `\` and Backspace |
|`MAGIC_HOST_NKRO` |`NK_ON` |Enable N-key rollover |
|`MAGIC_UNHOST_NKRO` |`NK_OFF` |Disable N-key rollover |
|`MAGIC_TOGGLE_NKRO` |`NK_TOGG`|Toggle N-key rollover |
|`MAGIC_EE_HANDS_LEFT` |`EH_LEFT`|Set the master half of a split keyboard as the left hand (for `EE_HANDS`) |
|`MAGIC_EE_HANDS_RIGHT` |`EH_RGHT`|Set the master half of a split keyboard as the right hand (for `EE_HANDS`)|
|Key |Aliases |Description |
|-------------------------------------|---------|--------------------------------------------------------------------------|
|`QK_MAGIC_SWAP_CONTROL_CAPS_LOCK` |`CL_SWAP`|Swap Caps Lock and Left Control |
|`QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK` |`CL_NORM`|Unswap Caps Lock and Left Control |
|`QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK` |`CL_TOGG`|Toggle Caps Lock and Left Control swap |
|`QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON` |`CL_CTRL`|Treat Caps Lock as Control |
|`QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF` |`CL_CAPS`|Stop treating Caps Lock as Control |
|`QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK` |`EC_SWAP`|Swap Caps Lock and Escape |
|`QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK` |`EC_NORM`|Unswap Caps Lock and Escape |
|`QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK` |`EC_TOGG`|Toggle Caps Lock and Escape swap |
|`QK_MAGIC_SWAP_LCTL_LGUI` |`CG_LSWP`|Swap Left Control and GUI |
|`QK_MAGIC_UNSWAP_LCTL_LGUI` |`CG_LNRM`|Unswap Left Control and GUI |
|`QK_MAGIC_SWAP_RCTL_RGUI` |`CG_RSWP`|Swap Right Control and GUI |
|`QK_MAGIC_UNSWAP_RCTL_RGUI` |`CG_RNRM`|Unswap Right Control and GUI |
|`QK_MAGIC_SWAP_CTL_GUI` |`CG_SWAP`|Swap Control and GUI on both sides |
|`QK_MAGIC_UNSWAP_CTL_GUI` |`CG_NORM`|Unswap Control and GUI on both sides |
|`QK_MAGIC_TOGGLE_CTL_GUI` |`CG_TOGG`|Toggle Control and GUI swap on both sides |
|`QK_MAGIC_SWAP_LALT_LGUI` |`AG_LSWP`|Swap Left Alt and GUI |
|`QK_MAGIC_UNSWAP_LALT_LGUI` |`AG_LNRM`|Unswap Left Alt and GUI |
|`QK_MAGIC_SWAP_RALT_RGUI` |`AG_RSWP`|Swap Right Alt and GUI |
|`QK_MAGIC_UNSWAP_RALT_RGUI` |`AG_RNRM`|Unswap Right Alt and GUI |
|`QK_MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides |
|`QK_MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Alt and GUI on both sides |
|`QK_MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Alt and GUI swap on both sides |
|`QK_MAGIC_GUI_OFF` |`GU_OFF` |Disable the GUI keys |
|`QK_MAGIC_GUI_ON` |`GU_ON` |Enable the GUI keys |
|`QK_MAGIC_TOGGLE_GUI` |`GU_TOGG`|Toggles the status of the GUI keys |
|`QK_MAGIC_SWAP_GRAVE_ESC` |`GE_SWAP`|Swap <code>&#96;</code> and Escape |
|`QK_MAGIC_UNSWAP_GRAVE_ESC` |`GE_NORM`|Unswap <code>&#96;</code> and Escape |
|`QK_MAGIC_SWAP_BACKSLASH_BACKSPACE` |`BS_SWAP`|Swap `\` and Backspace |
|`QK_MAGIC_UNSWAP_BACKSLASH_BACKSPACE`|`BS_NORM`|Unswap `\` and Backspace |
|`QK_MAGIC_TOGGLE_BACKSLASH_BACKSPACE`|`BS_TOGG`|Toggle `\` and Backspace swap state |
|`QK_MAGIC_NKRO_ON` |`NK_ON` |Enable N-key rollover |
|`QK_MAGIC_NKRO_OFF` |`NK_OFF` |Disable N-key rollover |
|`QK_MAGIC_TOGGLE_NKRO` |`NK_TOGG`|Toggle N-key rollover |
|`QK_MAGIC_EE_HANDS_LEFT` |`EH_LEFT`|Set the master half of a split keyboard as the left hand (for `EE_HANDS`) |
|`QK_MAGIC_EE_HANDS_RIGHT` |`EH_RGHT`|Set the master half of a split keyboard as the right hand (for `EE_HANDS`)|

View file

@ -92,11 +92,10 @@ These keycodes allow the processing to fall through to lower layers in search of
For this example we will walk through an [older version of the default Clueboard 66% keymap](https://github.com/qmk/qmk_firmware/blob/ca01d94005f67ec4fa9528353481faa622d949ae/keyboards/clueboard/keymaps/default/keymap.c). You'll find it helpful to open that file in another browser window so you can look at everything in context.
There are 3 main sections of a `keymap.c` file you'll want to concern yourself with:
There are 2 main sections of a `keymap.c` file you'll want to concern yourself with:
* [The Definitions](#definitions)
* [The Layer/Keymap Datastructure](#layers-and-keymaps)
* [Custom Functions](#custom-functions), if any
### Definitions
@ -118,9 +117,11 @@ At the top of the file you'll find this:
// Layer names don't all need to be of the same
// length, and you can also skip them entirely
// and just use numbers.
#define _BL 0
#define _FL 1
#define _CL 2
enum layer_names {
_BL,
_FL,
_CL,
};
These are some handy definitions we can use when building our keymap and our custom function. The `GRAVE_MODS` definition will be used later in our custom function, and the following `_BL`, `_FL`, and `_CL` defines make it easier to refer to each of our layers.
@ -142,14 +143,15 @@ After this you'll find the layer definitions. Typically you'll have one or more
Here is an example of the Clueboard's base layer:
/* Keymap _BL: Base Layer (Default Layer)
*/
[_BL] = LAYOUT(
F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP, \
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN, \
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, \
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RO, KC_RSFT, KC_UP, \
KC_LCTL, KC_LGUI, KC_LALT, KC_MHEN, KC_SPC,KC_SPC, KC_HENK, KC_RALT, KC_RCTL, MO(_FL), KC_LEFT, KC_DOWN, KC_RGHT),
```c
[_BL] = LAYOUT(
F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_INT1, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_INT5, KC_SPC,KC_SPC, KC_INT4, KC_RALT, KC_RCTL, MO(_FL), KC_LEFT, KC_DOWN, KC_RGHT
),
```
Some interesting things to note about this:
@ -164,12 +166,15 @@ Some interesting things to note about this:
Our function layer is, from a code point of view, no different from the base layer. Conceptually, however, you will build that layer as an overlay, not a replacement. For many people this distinction does not matter, but as you build more complicated layering setups it matters more and more.
[_FL] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_DEL, BL_STEP, \
_______, _______, _______,_______,_______,_______,_______,_______,KC_PSCR,KC_SCRL, KC_PAUS, _______, _______, _______, _______, \
_______, _______, MO(_CL),_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, \
_______, _______, _______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, KC_PGUP, \
_______, _______, _______, _______, _______,_______, _______, _______, _______, MO(_FL), KC_HOME, KC_PGDN, KC_END),
```c
[_FL] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_DEL, BL_STEP,
_______, _______, _______,_______,_______,_______,_______,_______,KC_PSCR,KC_SCRL, KC_PAUS, _______, _______, _______, _______,
_______, _______, MO(_CL),_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______,
_______, _______, _______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, KC_PGUP,
_______, _______, _______, _______, _______,_______, _______, _______, _______, MO(_FL), KC_HOME, KC_PGDN, KC_END
),
```
Some interesting things to note:

View file

@ -28,7 +28,7 @@ If you did not configure your environment, or you have multiple keyboards, you c
Look at the output from that command, you should see something like this:
Ψ <github_username> keymap directory created in: /home/me/qmk_firmware/keyboards/clueboard/66/rev3/keymaps/<github_username>
Ψ Created a new keymap called <github_username> in: /home/me/qmk_firmware/keyboards/clueboard/66/rev3/keymaps/<github_username>.
This is the location of your new `keymap.c` file.
@ -40,7 +40,7 @@ Open your `keymap.c` file in your text editor. Inside this file you'll find the
This line indicates where the list of Layers begins. Below that you'll find lines containing `LAYOUT`, and these lines indicate the start of a layer. Below that line is the list of keys that comprise a particular layer.
!> When editing your keymap file be careful not to add or remove any commas. If you do you will prevent your firmware from compiling and it may not be easy to figure out where the extra, or missing, comma is.
!> When editing your keymap file be careful not to add or remove any commas. If you do, you will prevent your firmware from compiling and it may not be easy to figure out where the extra, or missing, comma is.
## Customize The Layout To Your Liking

View file

@ -106,6 +106,9 @@ jobs:
steps:
- name: Disable git safe directory checks
run : git config --global --add safe.directory '*'
- name: Checkout QMK
uses: actions/checkout@v3
with:

View file

@ -51,21 +51,21 @@ git remote set-url origin https://github.com/<your_username>/qmk_firmware.git
Now that you have both remotes configured, you need to update the references for the upstream repository, which is QMK's, by running:
```
git fetch upstream
git fetch --recurse-submodules upstream
```
At this point, resynchronize your branch to QMK's by running:
```
git reset --hard upstream/master
git reset --recurse-submodules --hard upstream/master
```
These steps will update the repository on your computer, but your GitHub fork will still be out of sync. To resynchronize your fork on GitHub, you need to push to your fork, instructing Git to override any remote changes that are not reflected in your local repository. To do this, run:
```
git push --force-with-lease
git push --recurse-submodules=on-demand --force-with-lease
```
!> **DO NOT** run `git push --force-with-lease` on a fork to which other users post commits. This will erase their commits.
!> **DO NOT** run `git push --recurse-submodules=on-demand --force-with-lease` on a fork to which other users post commits. This will erase their commits.
Now your GitHub fork, your local files, and QMK's repository are all the same. From here you can make further needed changes ([use a branch!](newbs_git_using_your_master_branch.md#making-changes)) and post them as normal.

View file

@ -27,7 +27,7 @@ For one shot layers, you need to call `set_oneshot_layer(LAYER, ONESHOT_START)`
For one shot mods, you need to call `set_oneshot_mods(MOD_BIT(KC_*))` to set it, or `clear_oneshot_mods()` to cancel it.
!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tap, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop.
!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tab, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop.
## Callbacks

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