Browse Source

Deploying to gh-pages from @ qmk/qmk_firmware@bacec14073b2e897d5a52caf12de5a6a1f7b4078 🚀

gh-pages
tzarc 1 year ago
parent
commit
3f48cfb17e
49 changed files with 1545 additions and 463 deletions
  1. +367
    -0
      ChangeLog/20230226.md
  2. +4
    -1
      _summary.md
  3. +17
    -0
      adc_driver.md
  4. +11
    -18
      breaking_changes.md
  5. +1
    -0
      breaking_changes_history.md
  6. +17
    -15
      config_options.md
  7. +4
    -6
      configurator_default_keymaps.md
  8. +2
    -2
      custom_matrix.md
  9. +1
    -10
      feature_auto_shift.md
  10. +50
    -0
      feature_combo.md
  11. +26
    -4
      feature_converters.md
  12. +237
    -105
      feature_leader_key.md
  13. +1
    -1
      feature_led_indicators.md
  14. +4
    -4
      feature_midi.md
  15. +77
    -0
      feature_os_detection.md
  16. +12
    -9
      feature_pointing_device.md
  17. +14
    -14
      feature_sequencer.md
  18. +6
    -0
      feature_split_keyboard.md
  19. +18
    -12
      feature_swap_hands.md
  20. +32
    -32
      feature_tap_dance.md
  21. +48
    -0
      feature_tri_layer.md
  22. +5
    -5
      feature_unicode.md
  23. +42
    -1
      flashing.md
  24. +1
    -1
      gpio_control.md
  25. +1
    -1
      hardware_keyboard_guidelines.md
  26. +139
    -0
      internals/leader.md
  27. +0
    -2
      ja/config_options.md
  28. +2
    -2
      ja/custom_matrix.md
  29. +2
    -2
      ja/feature_grave_esc.md
  30. +1
    -1
      ja/feature_led_indicators.md
  31. +1
    -1
      ja/hardware_keyboard_guidelines.md
  32. +5
    -3
      ja/keymap.md
  33. +0
    -2
      ja/other_vscode.md
  34. +0
    -19
      ja/tap_hold.md
  35. +49
    -47
      keycodes.md
  36. +32
    -30
      keycodes_basic.md
  37. +37
    -36
      keycodes_magic.md
  38. +23
    -17
      keymap.md
  39. +1
    -1
      newbs_building_firmware.md
  40. +1
    -1
      other_vscode.md
  41. +19
    -4
      platformdev_rp2040.md
  42. +38
    -21
      quantum_painter.md
  43. +55
    -0
      quantum_painter_lvgl.md
  44. +35
    -0
      reference_info_json.md
  45. +2
    -0
      squeezing_avr.md
  46. +98
    -26
      tap_hold.md
  47. +2
    -2
      zh-cn/feature_grave_esc.md
  48. +5
    -3
      zh-cn/keymap.md
  49. +0
    -2
      zh-cn/other_vscode.md

+ 367
- 0
ChangeLog/20230226.md 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))

+ 4
- 1
_summary.md View File

@ -85,6 +85,7 @@
* [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)
@ -92,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)
@ -99,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)
@ -136,7 +139,7 @@
* Breaking Changes
* [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
* [Most Recent ChangeLog](ChangeLog/20221126.md "QMK v0.19.0 - 2022 Nov 26")
* [Most Recent ChangeLog](ChangeLog/20230226.md "QMK v0.20.0 - 2023 Feb 26")
* [Past Breaking Changes](breaking_changes_history.md)
* C Development


+ 17
- 0
adc_driver.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


+ 11
- 18
breaking_changes.md View File

@ -10,34 +10,27 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
## 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 February 26, 2023.
The next Breaking Change is scheduled for May 28, 2023.
### Important Dates
* 2022 Nov 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2023 Jan 29 - `develop` closed to new PRs.
* 2023 Jan 29 - Call for testers.
* 2023 Feb 12 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2023 Feb 19 - `develop` is locked, only critical bugfix PRs merged.
* 2023 Feb 24 - `master` is locked, no PRs merged.
* 2023 Feb 26 - Merge `develop` to `master`.
* 2023 Feb 26 - `master` is unlocked. PRs 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?


+ 1
- 0
breaking_changes_history.md View File

@ -2,6 +2,7 @@
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


+ 17
- 15
config_options.md View File

@ -37,12 +37,7 @@ 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`
@ -169,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.
@ -212,6 +211,9 @@ If you define these options you will enable the associated feature, which may in
* 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
@ -325,7 +327,7 @@ 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`


+ 4
- 6
configurator_default_keymaps.md View File

@ -54,7 +54,7 @@ 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, 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,
@ -82,7 +82,7 @@ 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", "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",
@ -153,10 +153,9 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
```c
enum keyboard_keycodes {
CUSTOM_1 = SAFE_RANGE,
CUSTOM_1 = QK_KB_0,
CUSTOM_2,
CUSTOM_3,
NEW_SAFE_RANGE // Important!
};
```
@ -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


+ 2
- 2
custom_matrix.md 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;
}


+ 1
- 10
feature_auto_shift.md 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


+ 50
- 0
feature_combo.md View File

@ -328,6 +328,51 @@ If you, for example, use multiple base layers for different key layouts, one for
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:
@ -350,6 +395,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)


+ 26
- 4
feature_converters.md View File

@ -18,8 +18,14 @@ Currently the following converters are available:
| `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.
@ -81,6 +87,8 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
| [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:
@ -93,7 +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
@ -124,7 +135,7 @@ 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, Bit-C PRO, and Elite-Pi :id=promicro_rp2040
### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi :id=promicro_rp2040
Currently identical to [Adafruit KB2040](#kb2040).
@ -153,10 +164,18 @@ 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)
```
### 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:
@ -165,18 +184,21 @@ If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products
|----------------------------------------------------------------------------------|-------------------|
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
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.
### Elite-Pi :id=elite_pi
### RP2040 Community Edition :id=rp2040_ce_elite
Currently identical to [Adafruit KB2040](#kb2040), with support for the additional bottom row of pins.
Currently identical to [RP2040 Community Edition](#rp2040_ce), with support for the additional bottom row of pins.

+ 237
- 105
feature_leader_key.md View File

@ -1,165 +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 `QK_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 `QK_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 `QK_LEAD` key. Specifically, when you press the `QK_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 `QK_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:
Add the following to your `rules.mk`:
```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);
}
}
}
```make
LEADER_ENABLE = yes
```
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.
Then add the `QK_LEAD` keycode to your keymap.
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.
## Callbacks :id=callbacks
## Adding Leader Key Support
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.
To enable Leader Key, add the following line to your keymap's `rules.mk`:
```c
void leader_start_user(void) {
// Do something when the leader key is pressed
}
```make
LEADER_ENABLE = yes
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));
}
}
```
Place the following macro in your `keymap.c` or user space source file, before any functional code. It handles declaration of external variables that will be referenced by Leader Key codes that follows:
## 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
LEADER_EXTERNS();
#define LEADER_TIMEOUT 350
```
## Per Key Timing on Leader keys
### 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).
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).
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
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.
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.
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.
## Customization
### Strict Key Processing :id=strict-key-processing
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()`.
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.
The `leader_start()` function is called when you tap the `QK_LEAD` key, and the `leader_end()` function is called when either the leader sequence is completed, or the leader timeout is hit.
This gives a more expected behaviour for most users, however you may want to change this.
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 `QK_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;
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;
}
leader_end();
}
}
void leader_start(void) {
void leader_start_user(void) {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_start);
PLAY_SONG(leader_start_song);
#endif
}
void leader_end(void) {
if (did_leader_succeed) {
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_succeed);
#endif
} else {
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;
}
#ifdef AUDIO_ENABLE
PLAY_SONG(leader_fail);
if (did_leader_succeed) {
PLAY_SONG(leader_succeed_song);
} else {
PLAY_SONG(leader_fail_song);
}
#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.

+ 1
- 1
feature_led_indicators.md 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


+ 4
- 4
feature_midi.md View File

@ -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)


+ 77
- 0
feature_os_detection.md 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.

+ 12
- 9
feature_pointing_device.md 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.
@ -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_ |


+ 14
- 14
feature_sequencer.md 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


+ 6
- 0
feature_split_keyboard.md View File

@ -284,6 +284,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.


+ 18
- 12
feature_swap_hands.md 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. |
`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`.
|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_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. |

+ 32
- 32
feature_tap_dance.md View File

@ -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,7 +349,7 @@ 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)
};
```
@ -385,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;
@ -408,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:
@ -426,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);
@ -443,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)
};
```
@ -478,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;
@ -504,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:
@ -528,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);
@ -537,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)
};


+ 48
- 0
feature_tri_layer.md 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.

+ 5
- 5
feature_unicode.md View File

@ -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).


+ 42
- 1
flashing.md View 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.
@ -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.


+ 1
- 1
gpio_control.md 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


+ 1
- 1
hardware_keyboard_guidelines.md 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>`


+ 139
- 0
internals/leader.md View File

@ -0,0 +1,139 @@
# group `leader`
Leader Key
## Summary
Members | Descriptions
--------------------------------|---------------------------------------------
`public void `[`leader_start_user`](#group__leader_1gae7b6746b0c6bd83cada1e770a7d8315d)`(void)` | User callback, invoked when the leader sequence begins.
`public void `[`leader_end_user`](#group__leader_1ga20986d88ffc5f21f00eab4b5e9a03188)`(void)` | User callback, invoked when the leader sequence ends.
`public void `[`leader_start`](#group__leader_1ga1f5dad3a2df12d29023e48852ff638ba)`(void)` | Begin the leader sequence, resetting the buffer and timer.
`public void `[`leader_end`](#group__leader_1ga7ecc035ad29aed6d5ee3848725234b6c)`(void)` | End the leader sequence.
`public void `[`leader_task`](#group__leader_1gaa451b483f86840a1a3a773a074b73019)`(void)` |
`public bool `[`leader_sequence_active`](#group__leader_1gab52594aae07ec2f59cc6cc00dce9cc0b)`(void)` | Whether the leader sequence is active.
`public bool `[`leader_sequence_add`](#group__leader_1ga0b9825ee3240ffac41837664d10c36ff)`(uint16_t keycode)` | Add the given keycode to the sequence buffer.
`public bool `[`leader_sequence_timed_out`](#group__leader_1gadb5905415a54ffab4a47a8d3227b3942)`(void)` | Whether the leader sequence has reached the timeout.
`public void `[`leader_reset_timer`](#group__leader_1ga5a9246dc3f952a5522c188f747ce0722)`(void)` | Reset the leader sequence timer.
`public bool `[`leader_sequence_one_key`](#group__leader_1ga6bcdd330c94f7074361c21ad8ee901fd)`(uint16_t kc)` | Check the sequence buffer for the given keycode.
`public bool `[`leader_sequence_two_keys`](#group__leader_1ga6a09c0ae645990e9d219c62244c30e42)`(uint16_t kc1,uint16_t kc2)` | Check the sequence buffer for the given keycodes.
`public bool `[`leader_sequence_three_keys`](#group__leader_1ga0dd4e91b428947bfb5ddb6fd09b29c11)`(uint16_t kc1,uint16_t kc2,uint16_t kc3)` | Check the sequence buffer for the given keycodes.
`public bool `[`leader_sequence_four_keys`](#group__leader_1ga5f71174f1afa31112108336e0d782ff2)`(uint16_t kc1,uint16_t kc2,uint16_t kc3,uint16_t kc4)` | Check the sequence buffer for the given keycodes.
`public bool `[`leader_sequence_five_keys`](#group__leader_1ga2c565e3c2d21eac4b23db75a15a9fa2d)`(uint16_t kc1,uint16_t kc2,uint16_t kc3,uint16_t kc4,uint16_t kc5)` | Check the sequence buffer for the given keycodes.
## Members
#### `public void `[`leader_start_user`](#group__leader_1gae7b6746b0c6bd83cada1e770a7d8315d)`(void)`
User callback, invoked when the leader sequence begins.
#### `public void `[`leader_end_user`](#group__leader_1ga20986d88ffc5f21f00eab4b5e9a03188)`(void)`
User callback, invoked when the leader sequence ends.
#### `public void `[`leader_start`](#group__leader_1ga1f5dad3a2df12d29023e48852ff638ba)`(void)`
Begin the leader sequence, resetting the buffer and timer.
#### `public void `[`leader_end`](#group__leader_1ga7ecc035ad29aed6d5ee3848725234b6c)`(void)`
End the leader sequence.
#### `public void `[`leader_task`](#group__leader_1gaa451b483f86840a1a3a773a074b73019)`(void)`
#### `public bool `[`leader_sequence_active`](#group__leader_1gab52594aae07ec2f59cc6cc00dce9cc0b)`(void)`
Whether the leader sequence is active.
#### `public bool `[`leader_sequence_add`](#group__leader_1ga0b9825ee3240ffac41837664d10c36ff)`(uint16_t keycode)`
Add the given keycode to the sequence buffer.
If `LEADER_NO_TIMEOUT` is defined, the timer is reset if the buffer is empty.
#### Parameters
* `keycode` The keycode to add.
#### Returns
`true` if the keycode was added, `false` if the buffer is full.
#### `public bool `[`leader_sequence_timed_out`](#group__leader_1gadb5905415a54ffab4a47a8d3227b3942)`(void)`
Whether the leader sequence has reached the timeout.
If `LEADER_NO_TIMEOUT` is defined, the buffer must also contain at least one key.
#### `public void `[`leader_reset_timer`](#group__leader_1ga5a9246dc3f952a5522c188f747ce0722)`(void)`
Reset the leader sequence timer.
#### `public bool `[`leader_sequence_one_key`](#group__leader_1ga6bcdd330c94f7074361c21ad8ee901fd)`(uint16_t kc)`
Check the sequence buffer for the given keycode.
#### Parameters
* `kc` The keycode to check.
#### Returns
`true` if the sequence buffer matches.
#### `public bool `[`leader_sequence_two_keys`](#group__leader_1ga6a09c0ae645990e9d219c62244c30e42)`(uint16_t kc1,uint16_t kc2)`
Check the sequence buffer for the given keycodes.
#### Parameters
* `kc1` The first keycode to check.
* `kc2` The second keycode to check.
#### Returns
`true` if the sequence buffer matches.
#### `public bool `[`leader_sequence_three_keys`](#group__leader_1ga0dd4e91b428947bfb5ddb6fd09b29c11)`(uint16_t kc1,uint16_t kc2,uint16_t kc3)`
Check the sequence buffer for the given keycodes.
#### Parameters
* `kc1` The first keycode to check.
* `kc2` The second keycode to check.
* `kc3` The third keycode to check.
#### Returns
`true` if the sequence buffer matches.
#### `public bool `[`leader_sequence_four_keys`](#group__leader_1ga5f71174f1afa31112108336e0d782ff2)`(uint16_t kc1,uint16_t kc2,uint16_t kc3,uint16_t kc4)`
Check the sequence buffer for the given keycodes.
#### Parameters
* `kc1` The first keycode to check.
* `kc2` The second keycode to check.
* `kc3` The third keycode to check.
* `kc4` The fourth keycode to check.
#### Returns
`true` if the sequence buffer matches.
#### `public bool `[`leader_sequence_five_keys`](#group__leader_1ga2c565e3c2d21eac4b23db75a15a9fa2d)`(uint16_t kc1,uint16_t kc2,uint16_t kc3,uint16_t kc4,uint16_t kc5)`
Check the sequence buffer for the given keycodes.
#### Parameters
* `kc1` The first keycode to check.
* `kc2` The second keycode to check.
* `kc3` The third keycode to check.
* `kc4` The fourth keycode to check.
* `kc5` The fifth keycode to check.
#### Returns
`true` if the sequence buffer matches.

+ 0
- 2
ja/config_options.md 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)を見てください


+ 2
- 2
ja/custom_matrix.md 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;
}


+ 2
- 2
ja/feature_grave_esc.md 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> |
### 注意事項


+ 1
- 1
ja/feature_led_indicators.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


+ 1
- 1
ja/hardware_keyboard_guidelines.md 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>`


+ 5
- 3
ja/keymap.md 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` 定義は各レイヤーを参照しやすくします。


+ 0
- 2
ja/other_vscode.md 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 スタイルのキーバインドを好む人向け。これには他のオプションもあります。
いずれかの拡張機能をインストールしたら、再起動します。


+ 0
- 19
ja/tap_hold.md 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` に追加します:


+ 49
- 47
keycodes.md View File

@ -209,6 +209,8 @@ See also: [Basic Keycodes](keycodes_basic.md)
|`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/>
@ -400,43 +402,43 @@ See also: [Leader Key](feature_leader_key.md)
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_TOGGLE_BACKSLASH_BACKSPACE`|`BS_TOGG`|Toggle `\` and Backspace swap state |
|`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
@ -819,16 +821,16 @@ See also: [Space Cadet](feature_space_cadet.md)
See also: [Swap Hands](feature_swap_hands.md)
|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` |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


+ 32
- 30
keycodes_basic.md View File

@ -193,36 +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 |
|`KC_CONTROL_PANEL` |`KC_CPNL`|Open Control Panel |
|`KC_ASSISTANT` |`KC_ASST`|Launch Assistant |
|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


+ 37
- 36
keycodes_magic.md 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`)|

+ 23
- 17
keymap.md View File

@ -117,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.
@ -141,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_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),
```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:
@ -163,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:


+ 1
- 1
newbs_building_firmware.md 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.


+ 1
- 1
other_vscode.md View File

@ -97,7 +97,7 @@ Now, we will set up the MSYS2 window to show up in VSCode as the integrated term
No, really, that's it. The paths needed are already included when installing the packages, and it is much better about detecting the current workspace files and parsing them for IntelliSense.
## Plugins
## Extensions
There are a number of extensions that you may want to install:


+ 19
- 4
platformdev_rp2040.md View File

@ -4,7 +4,7 @@ The following table shows the current driver status for peripherals on RP2040 MC
| System | Support |
| ---------------------------------------------------------------- | ---------------------------------------------- |
| [ADC driver](adc_driver.md) | Support planned (no ETA) |
| [ADC driver](adc_driver.md) | :heavy_check_mark: |
| [Audio](audio_driver.md#pwm-hardware) | :heavy_check_mark: |
| [Backlight](feature_backlight.md) | :heavy_check_mark: |
| [I2C driver](i2c_driver.md) | :heavy_check_mark: |
@ -38,8 +38,8 @@ QMK RP2040 support builds upon ChibiOS and thus follows their convention for act
| RP2040 Peripheral | `mcuconf.h` values | `I2C_DRIVER` |
| ----------------- | ------------------ | ------------ |
| `I2C0` | `RP_I2C_USE_I2C0` | `I2CD1` |
| `I2C1` | `RP_I2C_USE_I2C1` | `I2CD2` |
| `I2C0` | `RP_I2C_USE_I2C0` | `I2CD0` |
| `I2C1` | `RP_I2C_USE_I2C1` | `I2CD1` |
To configure the I2C driver please read the [ChibiOS/ARM](i2c_driver.md#arm-configuration) section.
@ -74,7 +74,7 @@ This is the default board that is chosen, unless any other RP2040 board is selec
| Driver configuration define | Value |
| -------------------------------------------------------------------------- | ------------------------------------ |
| **I2C driver** | |
| `I2C_DRIVER` | `I2CD2` |
| `I2C_DRIVER` | `I2CD1` |
| `I2C1_SDA_PIN` | `GP2` |
| `I2C1_SCL_PIN` | `GP3` |
| **SPI driver** | |
@ -124,3 +124,18 @@ As the RP2040 does not have any internal flash memory it depends on an external
| W25X10CL | `#define RP2040_FLASH_W25X10CL` |
| IS25LP080 | `#define RP2040_FLASH_IS25LP080` |
| Generic 03H flash | `#define RP2040_FLASH_GENERIC_03H` |
## RP2040 Community Edition :id=rp2040_ce
The "RP2040 Community Edition" standard is a pinout that was defined by a committee of designers on the BastardKB Discord server.
These boards are designed to be a drop-in replacement for keyboards wanting an upgrade from ATmega32u4 based pro micros (eg. Elite-C).
| Pinout Compatible Controllers |
| -------------------------------------------------------------------------------- |
| [0xB2 Splinky](https://github.com/plut0nium/0xB2/) |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) |
| [Sea-Picro EXT](https://github.com/joshajohnson/sea-picro) |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) |
| [Frood](https://github.com/piit79/Frood) |
| [Liatris](https://splitkb.com/products/liatris) |

+ 38
- 21
quantum_painter.md View File

@ -32,15 +32,16 @@ Supported devices:
## Quantum Painter Configuration :id=quantum-painter-config
| Option | Default | Purpose |
|-----------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `QUANTUM_PAINTER_NUM_IMAGES` | `8` | The maximum number of images/animations that can be loaded at any one time. |
| `QUANTUM_PAINTER_NUM_FONTS` | `4` | The maximum number of fonts that can be loaded at any one time. |
| `QUANTUM_PAINTER_CONCURRENT_ANIMATIONS` | `4` | The maximum number of animations that can be executed at the same time. |
| `QUANTUM_PAINTER_LOAD_FONTS_TO_RAM` | `FALSE` | Whether or not fonts should be loaded to RAM. Relevant for fonts stored in off-chip persistent storage, such as external flash. |
| `QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE` | `32` | The limit of the amount of pixel data that can be transmitted in one transaction to the display. Higher values require more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_256_PALETTE` | `FALSE` | If 256-color palettes are supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_DEBUG` | _unset_ | Prints out significant amounts of debugging information to CONSOLE output. Significant performance degradation, use only for debugging. |
| Option | Default | Purpose |
|------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `QUANTUM_PAINTER_NUM_IMAGES` | `8` | The maximum number of images/animations that can be loaded at any one time. |
| `QUANTUM_PAINTER_NUM_FONTS` | `4` | The maximum number of fonts that can be loaded at any one time. |
| `QUANTUM_PAINTER_CONCURRENT_ANIMATIONS` | `4` | The maximum number of animations that can be executed at the same time. |
| `QUANTUM_PAINTER_LOAD_FONTS_TO_RAM` | `FALSE` | Whether or not fonts should be loaded to RAM. Relevant for fonts stored in off-chip persistent storage, such as external flash. |
| `QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE` | `32` | The limit of the amount of pixel data that can be transmitted in one transaction to the display. Higher values require more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_256_PALETTE` | `FALSE` | If 256-color palettes are supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS` | `FALSE` | If native color range is supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_DEBUG` | _unset_ | Prints out significant amounts of debugging information to CONSOLE output. Significant performance degradation, use only for debugging. |
Drivers have their own set of configurable options, and are described in their respective sections.
@ -63,7 +64,7 @@ options:
-d, --no-deltas Disables the use of delta frames when encoding animations.
-r, --no-rle Disables the use of RLE when encoding images.
-f FORMAT, --format FORMAT
Output format, valid types: pal256, pal16, pal4, pal2, mono256, mono16, mono4, mono2
Output format, valid types: rgb888, rgb565, pal256, pal16, pal4, pal2, mono256, mono16, mono4, mono2
-o OUTPUT, --output OUTPUT
Specify output directory. Defaults to same directory as input.
-i INPUT, --input INPUT
@ -77,16 +78,18 @@ The `OUTPUT` argument needs to be a directory, and will default to the same dire
The `FORMAT` argument can be any of the following:
| Format | Meaning |
|-----------|-----------------------------------------------------------------------|
| `pal256` | 256-color palette (requires `QUANTUM_PAINTER_SUPPORTS_256_PALETTE`) |
| `pal16` | 16-color palette |
| `pal4` | 4-color palette |
| `pal2` | 2-color palette |
| `mono256` | 256-shade grayscale (requires `QUANTUM_PAINTER_SUPPORTS_256_PALETTE`) |
| `mono16` | 16-shade grayscale |
| `mono4` | 4-shade grayscale |
| `mono2` | 2-shade grayscale |
| Format | Meaning |
|-----------|-------------------------------------------------------------------------------------------|
| `rgb888` | 16,777,216 colors in 8-8-8 RGB format (requires `QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS`) |
| `rgb565` | 65,536 colors in 5-6-5 RGB format (requires `QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS`) |
| `pal256` | 256-color palette (requires `QUANTUM_PAINTER_SUPPORTS_256_PALETTE`) |
| `pal16` | 16-color palette |
| `pal4` | 4-color palette |
| `pal2` | 2-color palette |
| `mono256` | 256-shade grayscale (requires `QUANTUM_PAINTER_SUPPORTS_256_PALETTE`) |
| `mono16` | 16-shade grayscale |
| `mono4` | 4-shade grayscale |
| `mono2` | 2-shade grayscale |
**Examples**:
@ -154,7 +157,7 @@ options:
-w, --raw Writes out the QFF file as raw data instead of c/h combo.
-r, --no-rle Disable the use of RLE to minimise converted image size.
-f FORMAT, --format FORMAT
Output format, valid types: pal256, pal16, pal4, pal2, mono256, mono16, mono4, mono2
Output format, valid types: rgb565, pal256, pal16, pal4, pal2, mono256, mono16, mono4, mono2
-u UNICODE_GLYPHS, --unicode-glyphs UNICODE_GLYPHS
Also generate the specified unicode glyphs.
-n, --no-ascii Disables output of the full ASCII character set (0x20..0x7E), exporting only the glyphs specified.
@ -215,6 +218,8 @@ The maximum number of displays can be configured by changing the following in yo
#define GC9A01_NUM_DEVICES 3
```
Native color format rgb565 is compatible with GC9A01
#### ** ILI9163 **
Enabling support for the ILI9163 in Quantum Painter is done by adding the following to `rules.mk`:
@ -239,6 +244,8 @@ The maximum number of displays can be configured by changing the following in yo
#define ILI9163_NUM_DEVICES 3
```
Native color format rgb565 is compatible with ILI9163
#### ** ILI9341 **
Enabling support for the ILI9341 in Quantum Painter is done by adding the following to `rules.mk`:
@ -263,6 +270,8 @@ The maximum number of displays can be configured by changing the following in yo
#define ILI9341_NUM_DEVICES 3
```
Native color format rgb565 is compatible with ILI9341
#### ** ILI9488 **
Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`:
@ -287,6 +296,8 @@ The maximum number of displays can be configured by changing the following in yo
#define ILI9488_NUM_DEVICES 3
```
Native color format rgb888 is compatible with ILI9488
#### ** SSD1351 **
Enabling support for the SSD1351 in Quantum Painter is done by adding the following to `rules.mk`:
@ -311,6 +322,8 @@ The maximum number of displays can be configured by changing the following in yo
#define SSD1351_NUM_DEVICES 3
```
Native color format rgb565 is compatible with SSD1351
#### ** ST7735 **
Enabling support for the ST7735 in Quantum Painter is done by adding the following to `rules.mk`:
@ -335,6 +348,8 @@ The maximum number of displays can be configured by changing the following in yo
#define ST7735_NUM_DEVICES 3
```
Native color format rgb565 is compatible with ST7735
!> Some ST7735 devices are known to have different drawing offsets -- despite being a 132x162 pixel display controller internally, some display panels are only 80x160, or smaller. These may require an offset to be applied; see `qp_set_viewport_offsets` above for information on how to override the offsets if they aren't correctly rendered.
#### ** ST7789 **
@ -361,6 +376,8 @@ The maximum number of displays can be configured by changing the following in yo
#define ST7789_NUM_DEVICES 3
```
Native color format rgb565 is compatible with ST7789
!> Some ST7789 devices are known to have different drawing offsets -- despite being a 240x320 pixel display controller internally, some display panels are only 240x240, or smaller. These may require an offset to be applied; see `qp_set_viewport_offsets` above for information on how to override the offsets if they aren't correctly rendered.
<!-- tabs:end -->


+ 55
- 0
quantum_painter_lvgl.md View File

@ -0,0 +1,55 @@
# Quantum Painter LVGL Integration :id=lvgl
LVGL (Light and Versatile Graphics Library) is an open-source graphics library providing everything you need to create an embedded GUI for your board with easy-to-use graphical elements.
LVGL integrates with [Quantum Painter's](quantum_painter.md) API and drivers to render to the display, the hardware supported by Quantum Painter is also supported by LVGL.
?> Keep in mind that enabling the LVGL integration has a big impact in firmware size, it is recommeded to use a supported MCU with >256 kB of flash space.
To learn more about LVGL and how to use it please take a look at their [official documentation](https://docs.lvgl.io/8.2/intro/)
## Enabling LVGL :id=lvgl-enabling
To enable LVGL to be built into your firmware, add the following to `rules.mk`:
```make
QUANTUM_PAINTER_ENABLE = yes
QUANTUM_PAINTER_DRIVERS = ......
QUANTUM_PAINTER_LVGL_INTEGRATION = yes
```
To configure the Quantum Painter Display Drivers please read the [Quantum Painter Display Drivers](quantum_painter.md#quantum-painter-drivers) section.
## Quantum Painter LVGL API :id=lvgl-api
### Quantum Painter LVGL Attach :id=lvgl-api-init
```c
bool qp_lvgl_attach(painter_device_t device);
```
The `qp_lvgl_attach` function is used to set up LVGL with the supplied display, and requires an already configured display.
```c
static painter_device_t display;
void keyboard_post_init_kb(void) {
display = qp_make_.......; // Create the display
qp_init(display, QP_ROTATION_0); // Initialise the display
if (qp_lvgl_attach(display)) { // Attach LVGL to the display
...Your code to draw // Run LVGL specific code to draw
}
}
```
To init. the display please read the [Display Initialisation](quantum_painter.md#quantum-painter-api-init) section.
!> Attaching LVGL to a display means LVGL subsequently "owns" the display. Using standard Quantum Painter drawing operations with the display after LVGL attachment will likely result in display artifacts.
### Quantum Painter LVGL Detach :id=lvgl-api-init
```c
void qp_lvgl_detach(void)
```
The `qp_lvgl_detach` function stops the internal LVGL ticks and releases resources related to it.
## Enabling/Disabling LVGL features :id=lvgl-configuring
You can overwrite LVGL specific features in your `lv_conf.h` file.

+ 35
- 0
reference_info_json.md View File

@ -113,6 +113,20 @@ Example:
}
```
### Additional Options
* `input_pressed_state`
* This configures state of the GPIO pins when the key is pressed - `1` for high, `0` for low
* Default: `0`
Example:
```json
"matrix_pins": {
"input_pressed_state": 1,
},
```
## Non-RGB LED Lighting
This section controls basic 2-pin LEDs, which typically pass through keyswitches and are soldered into the PCB, or are placed in PCB sockets.
@ -333,3 +347,24 @@ Example:
}
}
```
## Bootmagic
This section configures [Bootmagic Lite](feature_bootmagic.md) support.
The following options can be configured:
|Key |Description |
|---------|-----------------------------------------------------------------------------|
|`matrix` | A two item list describing the row and column location for the trigger key. |
Example:
```json
{
"bootmagic": {
"enabled": true,
"matrix": [0, 0]
},
}
```

+ 2
- 0
squeezing_avr.md View File

@ -193,6 +193,8 @@ That said, there are a number of Pro Micro replacements with ARM controllers:
* [SparkFun Pro Micro - RP2040](https://www.sparkfun.com/products/18288)
* [Blok](https://boardsource.xyz/store/628b95b494dfa308a6581622)
* [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040)
* [0xCB Helios](https://keeb.supply/products/0xcb-helios) ([Open Source](https://github.com/0xCB-dev/0xCB-Helios), DIY/PCBA/Shop)
* [Michi](https://github.com/ci-bus/michi-promicro-rp2040)
There are other, non-Pro Micro compatible boards out there. The most popular being:
* [WeAct Blackpill F411](https://www.aliexpress.com/item/1005001456186625.html) (~$6 USD)

+ 98
- 26
tap_hold.md View File

@ -118,7 +118,7 @@ The reason is that `TAPPING_TERM` is a macro that expands to a constant integer
The code which decides between the tap and hold actions of dual-role keys supports three different modes, in increasing order of preference for the hold action:
1. The default mode selects the hold action only if the dual-role key is held down longer than the tapping term. In this mode pressing other keys while the dual-role key is held down does not influence the tap-or-hold decision.
1. The default mode selects the hold action only if the dual-role key is held down longer than the tapping term. In this mode pressing other keys while the dual-role key is held down does not influence the tap-or-hold decision. In other words, this mode ignores interrupts.
2. The “permissive hold” mode, in addition to the default behavior, immediately selects the hold action when another key is tapped (pressed and then released) while the dual-role key is held down, even if this happens earlier than the tapping term. If another key is just pressed, but then the dual-role key is released before that other key (and earlier than the tapping term), this mode will still select the tap action.
@ -126,6 +126,73 @@ The code which decides between the tap and hold actions of dual-role keys suppor
Note that until the tap-or-hold decision completes (which happens when either the dual-role key is released, or the tapping term has expired, or the extra condition for the selected decision mode is satisfied), key events are delayed and not transmitted to the host immediately. The default mode gives the most delay (if the dual-role key is held down, this mode always waits for the whole tapping term), and the other modes may give less delay when other keys are pressed, because the hold action may be selected earlier.
### Comparison :id=comparison
To better illustrate the tap-or-hold decision modes, let us compare the expected output of each decision mode in a handful of tapping scenarios involving a mod-tap key (`LSFT_T(KC_A)`) and a regular key (`KC_B`) with the `TAPPING_TERM` set to 200ms.
By default, mod-taps behave like `HOLD_ON_OTHER_KEY_PRESS`, while layer-taps behave like "Ignore Interrupt" out of the box. If you want "Ignore Interrupt"-like behaviour for mod-taps, you must enable `IGNORE_MOD_TAP_INTERRUPT`, or return `false` in the `get_hold_on_other_key_press` function for all mod-taps.
Note: "`kc` held" in the "Physical key event" column means that the key wasn't physically released yet at this point in time.
#### Distinct taps (AABB) :id=distinct-taps
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 199 | `LSFT_T(KC_A)` up | a | a | a |
| 210 | `KC_B` down | ab | ab | ab |
| 220 | `KC_B` up | ab | ab | ab |
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 200 | `LSFT_T(KC_A)` held|<kbd>Shift</kbd>| <kbd>Shift</kbd> | <kbd>Shift</kbd> |
| 201 | `LSFT_T(KC_A)` up |<kbd>Shift</kbd>| <kbd>Shift</kbd> | <kbd>Shift</kbd> |
| 205 | `KC_B` down | b | b | b |
| 210 | `KC_B` up | b | b | b |
#### Nested tap (ABBA) :id=nested-tap
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 110 | `KC_B` down | | | B |
| 120 | `KC_B` up | | B | B |
| 199 | `LSFT_T(KC_A)` up | ab | B | B |
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 110 | `KC_B` down | | | B |
| 120 | `KC_B` up | | B | B |
| 200 | `LSFT_T(KC_A)` held| B | B | B |
| 210 | `LSFT_T(KC_A)` up | B | B | B |
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 200 | `LSFT_T(KC_A)` held|<kbd>Shift</kbd>| <kbd>Shift</kbd> | <kbd>Shift</kbd> |
| 205 | `KC_B` down | B | B | B |
| 210 | `KC_B` up | B | B | B |
| 220 | `LSFT_T(KC_A)` up | B | B | B |
#### Rolling keys (ABAB) :id=rolling-keys
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 110 | `KC_B` down | | | B |
| 130 | `LSFT_T(KC_A)` up | ab | ab | B |
| 140 | `KC_B` up | ab | ab | B |
| Time | Physical key event |Ignore Interrupt| `PERMISSIVE_HOLD` | `HOLD_ON_OTHER_KEY_PRESS` |
|------|--------------------|----------------|-------------------|----------------------------|
| 0 | `LSFT_T(KC_A)` down| | | |
| 110 | `KC_B` down | | | B |
| 200 | `LSFT_T(KC_A)` held| B | B | B |
| 205 | `LSFT_T(KC_A)` up | B | B | B |
| 210 | `KC_B` up | B | B | B |
### Default Mode
Example sequence 1 (the `L` key is also mapped to `KC_RGHT` on layer 2):
@ -179,8 +246,6 @@ since `SFT_T(KC_A)` is NOT held longer than the `TAPPING_TERM`.
However, the actual output would be capital `X` (`SHIFT` + `x`) due to reasons
explained under [Ignore Mod Tap Interrupt](#ignore-mod-tap-interrupt).
### Permissive Hold
The “permissive hold” mode can be enabled for all dual-role keys by adding the corresponding option to `config.h`:
@ -212,7 +277,7 @@ An example of a sequence that is affected by the “permissive hold” mode:
+---------------------------|--------+
```
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `PERMISSIVE_HOLD` option enabled, the Layer Tap key is considered as a layer switch if another key is tapped, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2). We could describe this sequence as a “nested press” (the modified key's key down and key up events are “nested” between the dual-role key's key down and key up events).
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `PERMISSIVE_HOLD` option enabled, the Layer Tap key is considered as a layer switch if another key is tapped, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2). We could describe this sequence as a “nested tap” (the modified key's key down and key up events are “nested” between the dual-role key's key down and key up events).
However, this slightly different sequence will not be affected by the “permissive hold” mode:
@ -235,7 +300,7 @@ However, this slightly different sequence will not be affected by the “permiss
In the sequence above the dual-role key is released before the other key is released, and if that happens within the tapping term, the “permissive hold” mode will still choose the tap action for the dual-role key, and the sequence will be registered as `al` by the host. We could describe this as a “rolling press” (the two keys' key down and key up events behave as if you were rolling a ball across the two keys, first pressing each key down in sequence and then releasing them in the same order).
?> The `PERMISSIVE_HOLD` option also affects Mod Tap keys, but this may not be noticeable if you do not also enable the `IGNORE_MOD_TAP_INTERRUPT` option for those keys, because the default handler for Mod Tap keys also considers both the “nested press” and “rolling press” sequences like shown above as a modifier hold, not the tap action. If you do not enable `IGNORE_MOD_TAP_INTERRUPT`, the effect of `PERMISSIVE_HOLD` on Mod Tap keys would be limited to reducing the delay before the key events are made visible to the host.
?> The `PERMISSIVE_HOLD` option is not noticeable if you also enable `HOLD_ON_OTHER_KEY_PRESS` because the latter option considers both the “nested tap” and “rolling press” sequences like shown above as a hold action, not the tap action. `HOLD_ON_OTHER_KEY_PRESS` makes the Tap-Or-Hold decision earlier in the chain of key events, thus taking a precedence over `PERMISSIVE_HOLD`. This remark also applies to default mod-taps.
For more granular control of this feature, you can add the following to your `config.h`:
@ -291,7 +356,7 @@ An example of a sequence that is affected by the “hold on other key press” m
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `HOLD_ON_OTHER_KEY_PRESS` option enabled, the Layer Tap key is considered as a layer switch if another key is pressed, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2).
?> The `HOLD_ON_OTHER_KEY_PRESS` option also affects Mod Tap keys, but this may not be noticeable if you do not also enable the `IGNORE_MOD_TAP_INTERRUPT` option for those keys, because the default handler for Mod Tap keys also considers the “rolling press” sequence like shown above as a modifier hold, not the tap action. If you do not enable `IGNORE_MOD_TAP_INTERRUPT`, the effect of `HOLD_ON_OTHER_KEY_PRESS` on Mod Tap keys would be limited to reducing the delay before the key events are made visible to the host.
?> The `HOLD_ON_OTHER_KEY_PRESS` option is essentially redundant with the default mod-tap behaviour. The only notable difference is that `HOLD_ON_OTHER_KEY_PRESS` reduces the delay before the key events are made visible to the host.
For more granular control of this feature, you can add the following to your `config.h`:
@ -355,69 +420,76 @@ However, if the `HOLD_ON_OTHER_KEY_PRESS` option is enabled in addition to `IGNO
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY
```
?> This option affects *all* dual-role keys.
You can then add the following function to your keymap:
```c
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case SFT_T(KC_SPC):
// Do not force the mod-tap key press to be handled as a modifier
// if any other key was pressed while the mod-tap key is held down.
return true;
return false;
default:
// Force the mod-tap key press to be handled as a modifier if any
// Force the dual-role key press to be handled as a modifier if any
// other key was pressed while the mod-tap key is held down.
return false;
return true;
}
}
```
## Tapping Force Hold
Note that you must return `false` in `get_hold_on_other_key_press` in order to apply `IGNORE_MOD_TAP_INTERRUPT` for a certain mod-tap key.
To enable `tapping force hold`, add the following to your `config.h`:
?> `IGNORE_MOD_TAP_INTERRUPT[_PER_KEY]` is being progressively phased out to align the (default) behavior and configuration of mod-taps with the rest of dual-role keys.
## Quick Tap Term
When the user holds a key after tapping it, the tapping function is repeated by default, rather than activating the hold function. This allows keeping the ability to auto-repeat the tapping function of a dual-role key. `QUICK_TAP_TERM` enables fine tuning of that ability. If set to `0`, it will remove the auto-repeat ability and activate the hold function instead.
`QUICK_TAP_TERM` is set to `TAPPING_TERM` by default, which is the maximum allowed value for `QUICK_TAP_TERM`. To override its value (in milliseconds) add the following to your `config.h`:
```c
#define TAPPING_FORCE_HOLD
#define QUICK_TAP_TERM 120
```
When the user holds a key after tapping it, the tapping function is repeated by default, rather than activating the hold function. This allows keeping the ability to auto-repeat the tapping function of a dual-role key. `TAPPING_FORCE_HOLD` removes that ability to let the user activate the hold function instead, in the case of holding the dual-role key after having tapped it.
Example:
- `SFT_T(KC_A)` Down
- `SFT_T(KC_A)` Up
- `SFT_T(KC_A)` Down
- wait until the tapping term expires...
- `SFT_T(KC_A)` Up
- (wait until tapping term expires...)
With default settings, `a` will be sent on the first release, then `a` will be sent on the second press allowing the computer to trigger its auto-repeat function.
With default settings, `a` will be sent on the first release, then `a` will be sent on the second press allowing the computer to trigger its auto repeat function until the key is released.
With `TAPPING_FORCE_HOLD`, the second press will be interpreted as a Shift, allowing to use it as a modifier shortly after having used it as a tap.
With `QUICK_TAP_TERM` configured, the timing between `SFT_T(KC_A)` up and `SFT_T(KC_A)` down must be within `QUICK_TAP_TERM` to trigger auto repeat. Otherwise the second press will be sent as a Shift. If `QUICK_TAP_TERM` is set to `0`, the second press will always be sent as a Shift, effectively disabling auto-repeat.
!> `TAPPING_FORCE_HOLD` will break anything that uses tapping toggles (Such as the `TT` layer keycode, and the One Shot Tap Toggle).
!> `QUICK_TAP_TERM` timing will also impact anything that uses tapping toggles (Such as the `TT` layer keycode, and the One Shot Tap Toggle).
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define TAPPING_FORCE_HOLD_PER_KEY
#define QUICK_TAP_TERM_PER_KEY
```
You can then add the following function to your keymap:
```c
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) {
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LT(1, KC_BSPC):
return true;
case SFT_T(KC_SPC):
return QUICK_TAP_TERM - 20;
default:
return false;
return QUICK_TAP_TERM;
}
}
```
?> If `QUICK_TAP_TERM` is set higher than `TAPPING_TERM`, it will default to `TAPPING_TERM`.
## Retro Tapping
To enable `retro tapping`, add the following to your `config.h`:


+ 2
- 2
zh-cn/feature_grave_esc.md View File

@ -11,7 +11,7 @@
## 使用方法
在配列中使用 `KC_GESC` 替换 `KC_GRAVE` (一般都在`1`键左边)。默认点击会输出 `KC_ESC`,按下Shift或GUI键时,点击会输出 `KC_GRV`
在配列中使用 `QK_GESC` 替换 `KC_GRAVE` (一般都在`1`键左边)。默认点击会输出 `KC_ESC`,按下Shift或GUI键时,点击会输出 `KC_GRV`
## 操作系统视角
@ -21,7 +21,7 @@
|键 |别名 |描述 |
|---------|-----------|------------------------------------------------------------------|
|`KC_GESC`|`GRAVE_ESC`|单击输出Escape, 按住Shift或GUI时输出<code>&#96;</code> |
|`QK_GESC`|`GRAVE_ESC`|单击输出Escape, 按住Shift或GUI时输出<code>&#96;</code> |
### 须留意


+ 5
- 3
zh-cn/keymap.md View File

@ -143,9 +143,11 @@ QMK键映射定义在C源文件中,其数据结构上是一个容纳了数组
// and just use numbers.
// 译:每一层为了便于识别可以起一个名字,下划线没有实际意义 - 叫STUFF之类的也行的,
// 译:层名不需要都一样长,甚至不定义这些直接用层号也是可以的
#define _BL 0
#define _FL 1
#define _CL 2
enum layer_names {
_BL,
_FL,
_CL,
};
以上是一些便于编写键映射及自定义函数时可用的预定义,`GRAVE_MODS` 后续会用在自定义函数中,之后的 `_BL`, `_FL``_CL` 便于我们在代码中引用这些层。


+ 0
- 2
zh-cn/other_vscode.md View File

@ -107,10 +107,8 @@
* [Git Extension Pack](https://marketplace.visualstudio.com/items?itemName=donjayamanne.git-extension-pack) - 提供了一系列的Git工具可以让你在QMK Firmware中使用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预览更符合Github的效果。
* [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风格的按键操作的人所准备。这样的扩展还有挺多。
安装扩展后需要重启VS Code。


Loading…
Cancel
Save