diff --git a/.github/ISSUE_TEMPLATE/blank.md b/.github/ISSUE_TEMPLATE/zzz_blank.md similarity index 100% rename from .github/ISSUE_TEMPLATE/blank.md rename to .github/ISSUE_TEMPLATE/zzz_blank.md diff --git a/.vscode/settings.json b/.vscode/settings.json index 0caee2241dc2..f17b9e23e3e1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,7 @@ "files.associations": { "*.h": "c", "*.c": "c", + "*.inc": "c", "*.cpp": "cpp", "*.hpp": "cpp", "xstddef": "c", diff --git a/bin/qmk b/bin/qmk index 60555d3d709b..7592eefd933e 100755 --- a/bin/qmk +++ b/bin/qmk @@ -2,10 +2,8 @@ """CLI wrapper for running QMK commands. """ import os -import subprocess import sys from importlib.util import find_spec -from time import strftime # Add the QMK python libs to our path script_dir = os.path.dirname(os.path.realpath(__file__)) @@ -35,16 +33,6 @@ with open(os.path.join(qmk_dir, 'requirements.txt'), 'r') as fd: print('Please run `pip3 install -r requirements.txt` to install the python dependencies.') exit(255) -# Figure out our version -# TODO(skullydazed/anyone): Find a method that doesn't involve git. This is slow in docker and on windows. -command = ['git', 'describe', '--abbrev=6', '--dirty', '--always', '--tags'] -result = subprocess.run(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - -if result.returncode == 0: - os.environ['QMK_VERSION'] = result.stdout.strip() -else: - os.environ['QMK_VERSION'] = 'nogit-' + strftime('%Y-%m-%d-%H:%M:%S') + '-dirty' - # Setup the CLI import milc # noqa diff --git a/build_json.mk b/build_json.mk index e04786144cae..087944cc418f 100644 --- a/build_json.mk +++ b/build_json.mk @@ -23,4 +23,4 @@ endif # Generate the keymap.c $(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) - bin/qmk json-keymap --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) + bin/qmk json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) diff --git a/build_keyboard.mk b/build_keyboard.mk index b086420653f4..4108704875d2 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -231,44 +231,19 @@ endif # We can assume a ChibiOS target When MCU_FAMILY is defined since it's # not used for LUFA ifdef MCU_FAMILY - FIRMWARE_FORMAT?=bin PLATFORM=CHIBIOS + PLATFORM_KEY=chibios + FIRMWARE_FORMAT?=bin else ifdef ARM_ATSAM PLATFORM=ARM_ATSAM + PLATFORM_KEY=arm_atsam FIRMWARE_FORMAT=bin else PLATFORM=AVR + PLATFORM_KEY=avr FIRMWARE_FORMAT?=hex endif -ifeq ($(PLATFORM),CHIBIOS) - include $(TMK_PATH)/chibios.mk - OPT_OS = chibios - ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_5)/boards/$(BOARD)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_4)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_4)/boards/$(BOARD)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_3)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_3)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_3)/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_3)/boards/$(BOARD)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_2)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_2)/boards/$(BOARD)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_1)/bootloader_defs.h - else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(KEYBOARD_PATH_1)/boards/$(BOARD)/bootloader_defs.h - else ifneq ("$(wildcard $(TOP_DIR)/drivers/boards/$(BOARD)/bootloader_defs.h)","") - OPT_DEFS += -include $(TOP_DIR)/drivers/boards/$(BOARD)/bootloader_defs.h - endif -endif - # Find all of the config.h files and add them to our CONFIG_H define. CONFIG_H := ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","") @@ -304,11 +279,6 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","") POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h endif -# Save the defines and includes here, so we don't include any keymap specific ones -PROJECT_DEFS := $(OPT_DEFS) -PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS) -PROJECT_CONFIG := $(CONFIG_H) - # Userspace setup and definitions ifeq ("$(USER_NAME)","") USER_NAME := $(KEYMAP) @@ -354,23 +324,17 @@ SRC += $(TMK_COMMON_SRC) OPT_DEFS += $(TMK_COMMON_DEFS) EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS) -ifeq ($(PLATFORM),AVR) -ifeq ($(strip $(PROTOCOL)), VUSB) - include $(TMK_PATH)/protocol/vusb.mk +include $(TMK_PATH)/$(PLATFORM_KEY).mk +ifneq ($(strip $(PROTOCOL)),) + include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk else - include $(TMK_PATH)/protocol/lufa.mk -endif - include $(TMK_PATH)/avr.mk -endif - -ifeq ($(PLATFORM),ARM_ATSAM) - include $(TMK_PATH)/arm_atsam.mk - include $(TMK_PATH)/protocol/arm_atsam.mk + include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk endif -ifeq ($(PLATFORM),CHIBIOS) - include $(TMK_PATH)/protocol/chibios.mk -endif +# TODO: remove this bodge? +PROJECT_DEFS := $(OPT_DEFS) +PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS) +PROJECT_CONFIG := $(CONFIG_H) ifeq ($(strip $(VISUALIZER_ENABLE)), yes) VISUALIZER_DIR = $(QUANTUM_DIR)/visualizer diff --git a/build_test.mk b/build_test.mk index cac2cba50926..d13d9a515b84 100644 --- a/build_test.mk +++ b/build_test.mk @@ -41,6 +41,7 @@ all: elf VPATH += $(COMMON_VPATH) PLATFORM:=TEST +PLATFORM_KEY:=test ifneq ($(filter $(FULL_TESTS),$(TEST)),) include tests/$(TEST)/rules.mk diff --git a/common_features.mk b/common_features.mk index f7e4c3286d7c..50b1127dc60d 100644 --- a/common_features.mk +++ b/common_features.mk @@ -13,52 +13,42 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -SERIAL_DIR := $(QUANTUM_DIR)/serial_link SERIAL_PATH := $(QUANTUM_PATH)/serial_link -SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c) -SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c) -SERIAL_DEFS += -DSERIAL_LINK_ENABLE -COMMON_VPATH += $(SERIAL_PATH) + +QUANTUM_SRC += \ + $(QUANTUM_DIR)/quantum.c \ + $(QUANTUM_DIR)/keymap_common.c \ + $(QUANTUM_DIR)/keycode_config.c ifeq ($(strip $(API_SYSEX_ENABLE)), yes) OPT_DEFS += -DAPI_SYSEX_ENABLE - SRC += $(QUANTUM_DIR)/api/api_sysex.c OPT_DEFS += -DAPI_ENABLE - SRC += $(QUANTUM_DIR)/api.c MIDI_ENABLE=yes + SRC += $(QUANTUM_DIR)/api/api_sysex.c + SRC += $(QUANTUM_DIR)/api.c endif -MUSIC_ENABLE := 0 - ifeq ($(strip $(AUDIO_ENABLE)), yes) OPT_DEFS += -DAUDIO_ENABLE - MUSIC_ENABLE := 1 + MUSIC_ENABLE = yes SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c - ifeq ($(PLATFORM),AVR) - SRC += $(QUANTUM_DIR)/audio/audio.c - else - SRC += $(QUANTUM_DIR)/audio/audio_arm.c - endif + SRC += $(QUANTUM_DIR)/audio/audio_$(PLATFORM_KEY).c SRC += $(QUANTUM_DIR)/audio/voices.c SRC += $(QUANTUM_DIR)/audio/luts.c endif ifeq ($(strip $(MIDI_ENABLE)), yes) OPT_DEFS += -DMIDI_ENABLE - MUSIC_ENABLE := 1 + MUSIC_ENABLE = yes SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c endif -ifeq ($(MUSIC_ENABLE), 1) +MUSIC_ENABLE ?= no +ifeq ($(MUSIC_ENABLE), yes) SRC += $(QUANTUM_DIR)/process_keycode/process_music.c endif -ifeq ($(strip $(COMBO_ENABLE)), yes) - OPT_DEFS += -DCOMBO_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c -endif - ifeq ($(strip $(STENO_ENABLE)), yes) OPT_DEFS += -DSTENO_ENABLE VIRTSER_ENABLE ?= yes @@ -80,28 +70,6 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) SRC += $(QUANTUM_DIR)/pointing_device.c endif -ifeq ($(strip $(UCIS_ENABLE)), yes) - OPT_DEFS += -DUCIS_ENABLE - UNICODE_COMMON := yes - SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c -endif - -ifeq ($(strip $(UNICODEMAP_ENABLE)), yes) - OPT_DEFS += -DUNICODEMAP_ENABLE - UNICODE_COMMON := yes - SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c -endif - -ifeq ($(strip $(UNICODE_ENABLE)), yes) - OPT_DEFS += -DUNICODE_ENABLE - UNICODE_COMMON := yes - SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c -endif - -ifeq ($(strip $(UNICODE_COMMON)), yes) - SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c -endif - VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c EEPROM_DRIVER ?= vendor ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),) @@ -141,6 +109,10 @@ else SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c OPT_DEFS += -DEEPROM_EMU_STM32F072xB OPT_DEFS += -DSTM32_EEPROM_ENABLE + else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),) + OPT_DEFS += -DEEPROM_DRIVER + COMMON_VPATH += $(DRIVER_PATH)/eeprom + SRC += eeprom_driver.c eeprom_stm32_L0_L1.c else # This will effectively work the same as "transient" if not supported by the chip SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c @@ -159,7 +131,6 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/rgblight.c CIE1931_CURVE := yes - LED_BREATHING_TABLE := yes RGB_KEYCODES_ENABLE := yes ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER @@ -246,31 +217,18 @@ ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes) SRC += $(QUANTUM_DIR)/process_keycode/process_rgb.c endif -ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) - OPT_DEFS += -DTAP_DANCE_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c -endif - -ifeq ($(strip $(KEY_LOCK_ENABLE)), yes) - OPT_DEFS += -DKEY_LOCK_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c -endif - ifeq ($(strip $(PRINTING_ENABLE)), yes) OPT_DEFS += -DPRINTING_ENABLE SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c SRC += $(TMK_DIR)/protocol/serial_uart.c endif -ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) - OPT_DEFS += -DAUTO_SHIFT_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c - ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes) - OPT_DEFS += -DAUTO_SHIFT_MODIFIERS - endif -endif - ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes) + SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c) + SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c) + SERIAL_DEFS += -DSERIAL_LINK_ENABLE + COMMON_VPATH += $(SERIAL_PATH) + SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC)) OPT_DEFS += $(SERIAL_DEFS) VAPTH += $(SERIAL_PATH) @@ -298,24 +256,23 @@ VALID_BACKLIGHT_TYPES := pwm software custom BACKLIGHT_ENABLE ?= no BACKLIGHT_DRIVER ?= pwm ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) - SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),) $(error BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type) endif COMMON_VPATH += $(QUANTUM_DIR)/backlight SRC += $(QUANTUM_DIR)/backlight/backlight.c + SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c OPT_DEFS += -DBACKLIGHT_ENABLE ifeq ($(strip $(BACKLIGHT_DRIVER)), custom) OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER - else ifeq ($(strip $(BACKLIGHT_DRIVER)), software) - SRC += $(QUANTUM_DIR)/backlight/backlight_soft.c else - ifeq ($(PLATFORM),AVR) - SRC += $(QUANTUM_DIR)/backlight/backlight_avr.c + SRC += $(QUANTUM_DIR)/backlight/backlight_driver_common.c + ifeq ($(strip $(BACKLIGHT_DRIVER)), pwm) + SRC += $(QUANTUM_DIR)/backlight/backlight_$(PLATFORM_KEY).c else - SRC += $(QUANTUM_DIR)/backlight/backlight_arm.c + SRC += $(QUANTUM_DIR)/backlight/backlight_$(strip $(BACKLIGHT_DRIVER)).c endif endif endif @@ -351,11 +308,6 @@ ifeq ($(strip $(CIE1931_CURVE)), yes) LED_TABLES := yes endif -ifeq ($(strip $(LED_BREATHING_TABLE)), yes) - OPT_DEFS += -DUSE_LED_BREATHING_TABLE - LED_TABLES := yes -endif - ifeq ($(strip $(LED_TABLES)), yes) SRC += $(QUANTUM_DIR)/led_tables.c endif @@ -370,34 +322,16 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes) include $(TMK_DIR)/protocol/usb_hid.mk endif +ifeq ($(strip $(WPM_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/wpm.c + OPT_DEFS += -DWPM_ENABLE +endif + ifeq ($(strip $(ENCODER_ENABLE)), yes) SRC += $(QUANTUM_DIR)/encoder.c OPT_DEFS += -DENCODER_ENABLE endif -HAPTIC_ENABLE ?= no -ifneq ($(strip $(HAPTIC_ENABLE)),no) - COMMON_VPATH += $(DRIVER_PATH)/haptic - SRC += haptic.c - OPT_DEFS += -DHAPTIC_ENABLE -endif - -ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), ) - SRC += DRV2605L.c - QUANTUM_LIB_SRC += i2c_master.c - OPT_DEFS += -DDRV2605L -endif - -ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), ) - SRC += solenoid.c - OPT_DEFS += -DSOLENOID_ENABLE -endif - -ifeq ($(strip $(HD44780_ENABLE)), yes) - SRC += drivers/avr/hd44780.c - OPT_DEFS += -DHD44780_ENABLE -endif - ifeq ($(strip $(VELOCIKEY_ENABLE)), yes) OPT_DEFS += -DVELOCIKEY_ENABLE SRC += $(QUANTUM_DIR)/velocikey.c @@ -416,26 +350,11 @@ ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes) SRC += $(QUANTUM_DIR)/dynamic_keymap.c endif -ifeq ($(strip $(LEADER_ENABLE)), yes) - SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c - OPT_DEFS += -DLEADER_ENABLE -endif - - ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes) - SRC += $(QUANTUM_DIR)/dip_switch.c - OPT_DEFS += -DDIP_SWITCH_ENABLE + OPT_DEFS += -DDIP_SWITCH_ENABLE + SRC += $(QUANTUM_DIR)/dip_switch.c endif -include $(DRIVER_PATH)/qwiic/qwiic.mk - -QUANTUM_SRC:= \ - $(QUANTUM_DIR)/quantum.c \ - $(QUANTUM_DIR)/keymap_common.c \ - $(QUANTUM_DIR)/keycode_config.c - - - VALID_CUSTOM_MATRIX_TYPES:= yes lite no CUSTOM_MATRIX ?= no @@ -493,6 +412,29 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) COMMON_VPATH += $(QUANTUM_PATH)/split_common endif +HAPTIC_ENABLE ?= no +ifneq ($(strip $(HAPTIC_ENABLE)),no) + COMMON_VPATH += $(DRIVER_PATH)/haptic + SRC += haptic.c + OPT_DEFS += -DHAPTIC_ENABLE +endif + +ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), ) + SRC += DRV2605L.c + QUANTUM_LIB_SRC += i2c_master.c + OPT_DEFS += -DDRV2605L +endif + +ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), ) + SRC += solenoid.c + OPT_DEFS += -DSOLENOID_ENABLE +endif + +ifeq ($(strip $(HD44780_ENABLE)), yes) + SRC += drivers/avr/hd44780.c + OPT_DEFS += -DHD44780_ENABLE +endif + ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes) OPT_DEFS += -DOLED_DRIVER_ENABLE COMMON_VPATH += $(DRIVER_PATH)/oled @@ -500,10 +442,34 @@ ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes) SRC += oled_driver.c endif +include $(DRIVER_PATH)/qwiic/qwiic.mk + +ifeq ($(strip $(UCIS_ENABLE)), yes) + OPT_DEFS += -DUCIS_ENABLE + UNICODE_COMMON := yes + SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c +endif + +ifeq ($(strip $(UNICODEMAP_ENABLE)), yes) + OPT_DEFS += -DUNICODEMAP_ENABLE + UNICODE_COMMON := yes + SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c +endif + +ifeq ($(strip $(UNICODE_ENABLE)), yes) + OPT_DEFS += -DUNICODE_ENABLE + UNICODE_COMMON := yes + SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c +endif + +ifeq ($(strip $(UNICODE_COMMON)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c +endif + SPACE_CADET_ENABLE ?= yes ifeq ($(strip $(SPACE_CADET_ENABLE)), yes) - SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c - OPT_DEFS += -DSPACE_CADET_ENABLE + SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c + OPT_DEFS += -DSPACE_CADET_ENABLE endif MAGIC_ENABLE ?= yes @@ -522,3 +488,31 @@ ifeq ($(strip $(DYNAMIC_MACRO_ENABLE)), yes) SRC += $(QUANTUM_DIR)/process_keycode/process_dynamic_macro.c OPT_DEFS += -DDYNAMIC_MACRO_ENABLE endif + +ifeq ($(strip $(COMBO_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c + OPT_DEFS += -DCOMBO_ENABLE +endif + +ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c + OPT_DEFS += -DTAP_DANCE_ENABLE +endif + +ifeq ($(strip $(KEY_LOCK_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c + OPT_DEFS += -DKEY_LOCK_ENABLE +endif + +ifeq ($(strip $(LEADER_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c + OPT_DEFS += -DLEADER_ENABLE +endif + +ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c + OPT_DEFS += -DAUTO_SHIFT_ENABLE + ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes) + OPT_DEFS += -DAUTO_SHIFT_MODIFIERS + endif +endif diff --git a/docs/README.md b/docs/README.md index 9f9ca166bdf6..4fd872688586 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,24 +9,35 @@ ## What is QMK Firmware? -QMK (*Quantum Mechanical Keyboard*) is an open source community that maintains QMK Firmware, QMK Toolbox, qmk.fm, and these docs. QMK Firmware is a keyboard firmware based on the [tmk\_keyboard](http://github.com/tmk/tmk_keyboard) with some useful features for Atmel AVR controllers, and more specifically, the [OLKB product line](http://olkb.com), the [ErgoDox EZ](http://www.ergodox-ez.com) keyboard, and the [Clueboard product line](http://clueboard.co/). It has also been ported to ARM chips using ChibiOS. You can use it to power your own hand-wired or custom keyboard PCB. +QMK (*Quantum Mechanical Keyboard*) is an open source community centered around developing computer input devices. The community encompasses all sorts of input devices, such as keyboards, mice, and MIDI devices. A core group of collaborators maintains [QMK Firmware](https://github.com/qmk/qmk_firmware), [QMK Configurator](https://config.qmk.fm), [QMK Toolbox](https://github.com/qmk/qmk_toolbox), [qmk.fm](https://qmk.fm), and this documentation with the help of community members like you. -## How to Get It +## Get Started -If you plan on contributing a keymap, keyboard, or features to QMK, the easiest thing to do is [fork the repo through Github](https://github.com/qmk/qmk_firmware#fork-destination-box), and clone your repo locally to make your changes, push them, then open a [Pull Request](https://github.com/qmk/qmk_firmware/pulls) from your fork. +Totally new to QMK? There are two ways to get started: -Otherwise, you can clone it directly with `git clone https://github.com/qmk/qmk_firmware`. Do not download the zip or tar files; a git repository is required to download the submodules in order to compile. +* Basic: [QMK Configurator](https://config.qmk.fm) + * Just select your keyboard from the dropdown and program your keyboard. + * We have an [introductory video](https://www.youtube.com/watch?v=-imgglzDMdY) you can watch. + * There is also an overview [document you can read](newbs_building_firmware_configurator.md). +* Advanced: [Use The Source](newbs.md) + * More powerful, but harder to use -## How to Compile +## Make It Yours -Before you are able to compile, you'll need to [install an environment](getting_started_build_tools.md) for AVR or/and ARM development. Once that is complete, you'll use the `make` command to build a keyboard and keymap with the following notation: +QMK has lots of [features](features.md) to explore, and a good deal of reference documentation to dig through. Most features are taken advantage of by modifying your [keymap](keymap.md), and changing the [keycodes](keycodes.md). - make planck/rev4:default +## Need help? -This would build the `rev4` revision of the `planck` with the `default` keymap. Not all keyboards have revisions (also called subprojects or folders), in which case, it can be omitted: +Check out the [support page](support.md) to see how you can get help using QMK. - make preonic:default +## Give Back -## How to Customize +There are a lot of ways you can contribute to the QMK Community. The easiest way to get started is to use it and spread the word to your friends. -QMK has lots of [features](features.md) to explore, and a good deal of [reference documentation](http://docs.qmk.fm) to dig through. Most features are taken advantage of by modifying your [keymap](keymap.md), and changing the [keycodes](keycodes.md). +* Help people out on our forums and chat rooms: + * [/r/olkb](https://www.reddit.com/r/olkb/) + * [Discord Server](https://discord.gg/Uq7gcHh) +* Contribute to our documentation by clicking "Edit This Page" at the bottom +* [Translate our documentation into your language](translating.md) +* [Report a bug](https://github.com/qmk/qmk_firmware/issues/new/choose) +* [Open a Pull Request](contributing.md) diff --git a/docs/_summary.md b/docs/_summary.md index a429138b8fbe..4a6e6996eba5 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -1,130 +1,162 @@ -* [Complete Newbs Guide](newbs.md) - * [Getting Started](newbs_getting_started.md) +* Tutorial + * [Introduction](newbs.md) + * [Setup](newbs_getting_started.md) * [Building Your First Firmware](newbs_building_firmware.md) * [Flashing Firmware](newbs_flashing.md) * [Testing and Debugging](newbs_testing_debugging.md) - * [Best Git Practices](newbs_git_best_practices.md) - * [Using Your Fork's Master](newbs_git_using_your_master_branch.md) - * [Resolving Merge Conflicts](newbs_git_resolving_merge_conflicts.md) - * [Resynchronizing a Branch](newbs_git_resynchronize_a_branch.md) - * [Learning Resources](newbs_learn_more_resources.md) + * [Getting Help/Support](support.md) + * [Other Resources](newbs_learn_more_resources.md) -* [QMK Basics](README.md) - * [QMK Introduction](getting_started_introduction.md) - * [QMK CLI](cli.md) - * [QMK CLI Config](cli_configuration.md) - * [Contributing to QMK](contributing.md) - * [How to Use Github](getting_started_github.md) - * [Getting Help](getting_started_getting_help.md) - -* [Breaking Changes](breaking_changes.md) - * [My Pull Request Was Flagged](breaking_changes_instructions.md) - * [2019 Aug 30](ChangeLog/20190830.md) - -* [FAQ](faq.md) +* FAQs * [General FAQ](faq_general.md) * [Build/Compile QMK](faq_build.md) * [Debugging/Troubleshooting QMK](faq_debug.md) - * [Keymap](faq_keymap.md) - * [Driver Installation with Zadig](driver_installation_zadig.md) + * [Keymap FAQ](faq_keymap.md) + * [Glossary](reference_glossary.md) -* Detailed Guides - * [Install Build Tools](getting_started_build_tools.md) - * [Vagrant Guide](getting_started_vagrant.md) - * [Build/Compile Instructions](getting_started_make_guide.md) - * [Flashing Firmware](flashing.md) - * [Customizing Functionality](custom_quantum_functions.md) - * [Keymap Overview](keymap.md) +* Configurator + * [Overview](newbs_building_firmware_configurator.md) + * [Step by Step](configurator_step_by_step.md) + * [Troubleshooting](configurator_troubleshooting.md) + * QMK API + * [Overview](api_overview.md) + * [API Documentation](api_docs.md) + * [Keyboard Support](reference_configurator_support.md) -* [Hardware](hardware.md) - * [Compatible Microcontrollers](compatible_microcontrollers.md) - * [AVR Processors](hardware_avr.md) - * [Drivers](hardware_drivers.md) +* CLI + * [Overview](cli.md) + * [Configuration](cli_configuration.md) + * [Commands](cli_commands.md) -* Reference - * [Keyboard Guidelines](hardware_keyboard_guidelines.md) - * [Config Options](config_options.md) - * [Keycodes](keycodes.md) - * [Coding Conventions - C](coding_conventions_c.md) - * [Coding Conventions - Python](coding_conventions_python.md) - * [Documentation Best Practices](documentation_best_practices.md) - * [Documentation Templates](documentation_templates.md) - * [Glossary](reference_glossary.md) - * [Unit Testing](unit_testing.md) - * [Useful Functions](ref_functions.md) - * [Configurator Support](reference_configurator_support.md) - * [info.json Format](reference_info_json.md) - * [Python CLI Development](cli_development.md) +* Using QMK + * Guides + * [Customizing Functionality](custom_quantum_functions.md) + * [Driver Installation with Zadig](driver_installation_zadig.md) + * [Keymap Overview](keymap.md) + * [Vagrant Guide](getting_started_vagrant.md) + * Flashing + * [Flashing](flashing.md) + * [Flashing ATmega32A (ps2avrgb)](flashing_bootloadhid.md) + * IDEs + * [Using Eclipse with QMK](other_eclipse.md) + * [Using VSCode with QMK](other_vscode.md) + * Git Best Practices + * [Introduction](newbs_git_best_practices.md) + * [Your Fork](newbs_git_using_your_master_branch.md) + * [Merge Conflicts](newbs_git_resolving_merge_conflicts.md) + * [Fixing Your Branch](newbs_git_resynchronize_a_branch.md) + * Keyboard Building + * [Hand Wiring Guide](hand_wire.md) + * [ISP Flashing Guide](isp_flashing_guide.md) + + * Simple Keycodes + * [Full List](keycodes.md) + * [Basic Keycodes](keycodes_basic.md) + * [Modifier Keys](feature_advanced_keycodes.md) + * [Quantum Keycodes](quantum_keycodes.md) + + * Advanced Keycodes + * [Command](feature_command.md) + * [Dynamic Macros](feature_dynamic_macros.md) + * [Grave Escape](feature_grave_esc.md) + * [Leader Key](feature_leader_key.md) + * [Mod-Tap](mod_tap.md) + * [Macros](feature_macros.md) + * [Mouse Keys](feature_mouse_keys.md) + * [Space Cadet Shift](feature_space_cadet.md) + * [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md) + + * Software Features + * [Auto Shift](feature_auto_shift.md) + * [Combos](feature_combo.md) + * [Debounce API](feature_debounce_type.md) + * [Key Lock](feature_key_lock.md) + * [Layers](feature_layers.md) + * [One Shot Keys](one_shot_keys.md) + * [Pointing Device](feature_pointing_device.md) + * [Swap Hands](feature_swap_hands.md) + * [Tap Dance](feature_tap_dance.md) + * [Tap-Hold Configuration](tap_hold.md) + * [Terminal](feature_terminal.md) + * [Unicode](feature_unicode.md) + * [Userspace](feature_userspace.md) + * [WPM Calculation](feature_wpm.md) + + * Hardware Features + * Displays + * [HD44780 LCD Controller](feature_hd44780.md) + * [OLED Driver](feature_oled_driver.md) + * Lighting + * [Backlight](feature_backlight.md) + * [LED Matrix](feature_led_matrix.md) + * [RGB Lighting](feature_rgblight.md) + * [RGB Matrix](feature_rgb_matrix.md) + * [Audio](feature_audio.md) + * [Bluetooth](feature_bluetooth.md) + * [Bootmagic](feature_bootmagic.md) + * [Custom Matrix](custom_matrix.md) + * [DIP Switch](feature_dip_switch.md) + * [Encoders](feature_encoders.md) + * [Haptic Feedback](feature_haptic_feedback.md) + * [Proton C Conversion](proton_c_conversion.md) + * [PS/2 Mouse](feature_ps2_mouse.md) + * [Split Keyboard](feature_split_keyboard.md) + * [Stenography](feature_stenography.md) + * [Thermal Printer](feature_thermal_printer.md) + * [Velocikey](feature_velocikey.md) + +* Developing QMK + * Breaking Changes + * [Overview](breaking_changes.md) + * [My Pull Request Was Flagged](breaking_changes_instructions.md) + * History + * [2020 Feb 29](ChangeLog/20200229.md) + * [2019 Aug 30](ChangeLog/20190830.md) + + * C Development + * [ARM Debugging Guide](arm_debugging.md) + * [AVR Processors](hardware_avr.md) + * [Coding Conventions](coding_conventions_c.md) + * [Compatible Microcontrollers](compatible_microcontrollers.md) + * [Drivers](hardware_drivers.md) + * [ADC Driver](adc_driver.md) + * [I2C Driver](i2c_driver.md) + * [WS2812 Driver](ws2812_driver.md) + * [EEPROM Driver](eeprom_driver.md) + * [GPIO Controls](internals_gpio_control.md) + * [Keyboard Guidelines](hardware_keyboard_guidelines.md) -* [Features](features.md) - * [Basic Keycodes](keycodes_basic.md) - * [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md) - * [Quantum Keycodes](quantum_keycodes.md) - * [Advanced Keycodes](feature_advanced_keycodes.md) - * [Audio](feature_audio.md) - * [Auto Shift](feature_auto_shift.md) - * [Backlight](feature_backlight.md) - * [Bluetooth](feature_bluetooth.md) - * [Bootmagic](feature_bootmagic.md) - * [Combos](feature_combo.md) - * [Command](feature_command.md) - * [Debounce API](feature_debounce_type.md) - * [DIP Switch](feature_dip_switch.md) - * [Dynamic Macros](feature_dynamic_macros.md) - * [Encoders](feature_encoders.md) - * [Grave Escape](feature_grave_esc.md) - * [Haptic Feedback](feature_haptic_feedback.md) - * [HD44780 LCD Controller](feature_hd44780.md) - * [Key Lock](feature_key_lock.md) - * [Layouts](feature_layouts.md) - * [Leader Key](feature_leader_key.md) - * [LED Matrix](feature_led_matrix.md) - * [Macros](feature_macros.md) - * [Mouse Keys](feature_mouse_keys.md) - * [OLED Driver](feature_oled_driver.md) - * [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys) - * [Pointing Device](feature_pointing_device.md) - * [PS/2 Mouse](feature_ps2_mouse.md) - * [RGB Lighting](feature_rgblight.md) - * [RGB Matrix](feature_rgb_matrix.md) - * [Space Cadet](feature_space_cadet.md) - * [Split Keyboard](feature_split_keyboard.md) - * [Stenography](feature_stenography.md) - * [Swap Hands](feature_swap_hands.md) - * [Tap Dance](feature_tap_dance.md) - * [Terminal](feature_terminal.md) - * [Thermal Printer](feature_thermal_printer.md) - * [Unicode](feature_unicode.md) - * [Userspace](feature_userspace.md) - * [Velocikey](feature_velocikey.md) + * Python Development + * [Coding Conventions](coding_conventions_python.md) + * [QMK CLI Development](cli_development.md) -* For Makers and Modders - * [Hand Wiring Guide](hand_wire.md) - * [ISP Flashing Guide](isp_flashing_guide.md) - * [ARM Debugging Guide](arm_debugging.md) - * [ADC Driver](adc_driver.md) - * [I2C Driver](i2c_driver.md) - * [WS2812 Driver](ws2812_driver.md) - * [EEPROM Driver](eeprom_driver.md) - * [GPIO Controls](internals_gpio_control.md) - * [Custom Matrix](custom_matrix.md) - * [Proton C Conversion](proton_c_conversion.md) + * Configurator Development + * QMK API + * [Development Environment](api_development_environment.md) + * [Architecture Overview](api_development_overview.md) -* For a Deeper Understanding - * [How Keyboards Work](how_keyboards_work.md) - * [Understanding QMK](understanding_qmk.md) + * QMK Reference + * [Contributing to QMK](contributing.md) + * [Translating the QMK Docs](translating.md) + * [Config Options](config_options.md) + * [Make Documentation](getting_started_make_guide.md) + * [Documentation Best Practices](documentation_best_practices.md) + * [Documentation Templates](documentation_templates.md) + * [Community Layouts](feature_layouts.md) + * [Unit Testing](unit_testing.md) + * [Useful Functions](ref_functions.md) + * [info.json Format](reference_info_json.md) -* Other Topics - * [Using Eclipse with QMK](other_eclipse.md) - * [Using VSCode with QMK](other_vscode.md) - * [Support](support.md) - * [Translating the QMK Docs](translating.md) + * For a Deeper Understanding + * [How Keyboards Work](how_keyboards_work.md) + * [How a Matrix Works](how_a_matrix_works.md) + * [Understanding QMK](understanding_qmk.md) -* QMK Internals (In Progress) - * [Defines](internals_defines.md) - * [Input Callback Reg](internals_input_callback_reg.md) - * [Midi Device](internals_midi_device.md) - * [Midi Device Setup Process](internals_midi_device_setup_process.md) - * [Midi Util](internals_midi_util.md) - * [Send Functions](internals_send_functions.md) - * [Sysex Tools](internals_sysex_tools.md) + * QMK Internals (In Progress) + * [Defines](internals_defines.md) + * [Input Callback Reg](internals_input_callback_reg.md) + * [Midi Device](internals_midi_device.md) + * [Midi Device Setup Process](internals_midi_device_setup_process.md) + * [Midi Util](internals_midi_util.md) + * [Send Functions](internals_send_functions.md) + * [Sysex Tools](internals_sysex_tools.md) diff --git a/docs/adc_driver.md b/docs/adc_driver.md index 26e148adddfe..7c4e05efc4bc 100644 --- a/docs/adc_driver.md +++ b/docs/adc_driver.md @@ -2,7 +2,7 @@ QMK can leverage the Analog-to-Digital Converter (ADC) on supported MCUs to measure voltages on certain pins. This can be useful for implementing things such as battery level indicators for Bluetooth keyboards, or volume controls using a potentiometer, as opposed to a [rotary encoder](feature_encoders.md). -This driver is currently AVR-only. The values returned are 10-bit integers (0-1023) mapped between 0V and VCC (usually 5V or 3.3V). +This driver currently supports both AVR and a limited selection of ARM devices. The values returned are 10-bit integers (0-1023) mapped between 0V and VCC (usually 5V or 3.3V for AVR, 3.3V only for ARM), however on ARM there is more flexibility in control of operation through `#define`s if you need more precision. ## Usage @@ -20,6 +20,8 @@ Then place this include at the top of your code: ## Channels +### AVR + |Channel|AT90USB64/128|ATmega16/32U4|ATmega32A|ATmega328P| |-------|-------------|-------------|---------|----------| |0 |`F0` |`F0` |`A0` |`C0` | @@ -39,8 +41,84 @@ Then place this include at the top of your code: \* The ATmega328P possesses two extra ADC channels; however, they are not present on the DIP pinout, and are not shared with GPIO pins. You can use `adc_read()` directly to gain access to these. +### ARM + +Note that some of these pins are doubled-up on ADCs with the same channel. This is because the pins can be used for either ADC. + +Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-based, whereas the F3 has 4 ADCs and the channels are 1 based. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation. + +|ADC|Channel|STM32F0XX|STM32F3XX| +|---|-------|---------|---------| +|1 |0 |`A0` | | +|1 |1 |`A1` |`A0` | +|1 |2 |`A2` |`A1` | +|1 |3 |`A3` |`A2` | +|1 |4 |`A4` |`A3` | +|1 |5 |`A5` |`F4` | +|1 |6 |`A6` |`C0` | +|1 |7 |`A7` |`C1` | +|1 |8 |`B0` |`C2` | +|1 |9 |`B1` |`C3` | +|1 |10 |`C0` |`F2` | +|1 |11 |`C1` | | +|1 |12 |`C2` | | +|1 |13 |`C3` | | +|1 |14 |`C4` | | +|1 |15 |`C5` | | +|1 |16 | | | +|2 |1 | |`A4` | +|2 |2 | |`A5` | +|2 |3 | |`A6` | +|2 |4 | |`A7` | +|2 |5 | |`C4` | +|2 |6 | |`C0` | +|2 |7 | |`C1` | +|2 |8 | |`C2` | +|2 |9 | |`C3` | +|2 |10 | |`F2` | +|2 |11 | |`C5` | +|2 |12 | |`B2` | +|2 |13 | | | +|2 |14 | | | +|2 |15 | | | +|2 |16 | | | +|3 |1 | |`B1` | +|3 |2 | |`E9` | +|3 |3 | |`E13` | +|3 |4 | | | +|3 |5 | | | +|3 |6 | |`E8` | +|3 |7 | |`D10` | +|3 |8 | |`D11` | +|3 |9 | |`D12` | +|3 |10 | |`D13` | +|3 |11 | |`D14` | +|3 |12 | |`B0` | +|3 |13 | |`E7` | +|3 |14 | |`E10` | +|3 |15 | |`E11` | +|3 |16 | |`E12` | +|4 |1 | |`E14` | +|4 |2 | |`B12` | +|4 |3 | |`B13` | +|4 |4 | |`B14` | +|4 |5 | |`B15` | +|4 |6 | |`E8` | +|4 |7 | |`D10` | +|4 |8 | |`D11` | +|4 |9 | |`D12` | +|4 |10 | |`D13` | +|4 |11 | |`D14` | +|4 |12 | |`D8` | +|4 |13 | |`D9` | +|4 |14 | | | +|4 |15 | | | +|4 |16 | | | + ## Functions +### AVR + |Function |Description | |----------------------------|-------------------------------------------------------------------------------------------------------------------| |`analogReference(mode)` |Sets the analog voltage reference source. Must be one of `ADC_REF_EXTERNAL`, `ADC_REF_POWER` or `ADC_REF_INTERNAL`.| @@ -48,3 +126,28 @@ Then place this include at the top of your code: |`analogReadPin(pin)` |Reads the value from the specified QMK pin, eg. `F6` for ADC6 on the ATmega32U4. | |`pinToMux(pin)` |Translates a given QMK pin to a mux value. If an unsupported pin is given, returns the mux value for "0V (GND)". | |`adc_read(mux)` |Reads the value from the ADC according to the specified mux. See your MCU's datasheet for more information. | + +### ARM + +Note that care was taken to match all of the functions used for AVR devices, however complications in the ARM platform prevent that from always being possible. For example, the `STM32` chips do not have assigned Arduino pins. We could use the default pin numbers, but those numbers change based on the package type of the device. For this reason, please specify your target pins with their identifiers (`A0`, `F3`, etc.). Also note that there are some variants of functions that accept the target ADC for the pin. Some pins can be used for multiple ADCs, and this specified can help you pick which ADC will be used to interact with that pin. + +|Function |Description | +|----------------------------|--------------------------------------------------------------------------------------------------------------------| +|`analogReadPin(pin)` |Reads the value from the specified QMK pin, eg. `A0` for channel 0 on the STM32F0 and ADC1 channel 1 on the STM32F3. Note that if a pin can be used for multiple ADCs, it will pick the lower numbered ADC for this function. eg. `C0` will be channel 6 of ADC 1 when it could be used for ADC 2 as well.| +|`analogReadPinAdc(pin, adc)`|Reads the value from the specified QMK pin and ADC, eg. `C0, 1` will read from channel 6, ADC 2 instead of ADC 1. Note that the ADCs are 0-indexed for this function.| +|`pinToMux(pin)` |Translates a given QMK pin to a channel and ADC combination. If an unsupported pin is given, returns the mux value for "0V (GND)".| +|`adc_read(mux)` |Reads the value from the ADC according to the specified pin and adc combination. See your MCU's datasheet for more information.| + +## Configuration + +## ARM + +The ARM implementation of the ADC has a few additional options that you can override in your own keyboards and keymaps to change how it operates. + +|`#define` |Type |Default |Description| +|-------------------|------|---------------------|-----------| +|ADC_CIRCULAR_BUFFER|`bool`|`false` |If `TRUE`, then the implementation will use a circular buffer.| +|ADC_NUM_CHANNELS |`int` |`1` |Sets the number of channels that will be scanned as part of an ADC operation. The current implementation only supports `1`.| +|ADC_BUFFER_DEPTH |`int` |`2` |Sets the depth of each result. Since we are only getting a 12-bit result by default, we set this to `2` bytes so we can contain our one value. This could be set to 1 if you opt for a 8-bit or lower result.| +|ADC_SAMPLING_RATE |`int` |`ADC_SMPR_SMP_1P5` |Sets the sampling rate of the ADC. By default, it is set to the fastest setting. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.| +|ADC_RESOLUTION |`int` |`ADC_CFGR1_RES_12BIT`|The resolution of your result. We choose 12 bit by default, but you can opt for 12, 10, 8, or 6 bit. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.| diff --git a/docs/api_development_environment.md b/docs/api_development_environment.md new file mode 100644 index 000000000000..50647c429951 --- /dev/null +++ b/docs/api_development_environment.md @@ -0,0 +1,3 @@ +# Development Environment Setup + +To setup a development stack head over to the [qmk_web_stack](https://github.com/qmk/qmk_web_stack). diff --git a/docs/api_development_overview.md b/docs/api_development_overview.md new file mode 100644 index 000000000000..e55d0341006b --- /dev/null +++ b/docs/api_development_overview.md @@ -0,0 +1,44 @@ +# QMK Compiler Development Guide + +This page attempts to introduce developers to the QMK Compiler. It does not go into nitty gritty details- for that you should read code. What this will give you is a framework to hang your understanding on as you read the code. + +# Overview + +The QMK Compile API consists of a few movings parts: + +![Architecture Diagram](https://raw.githubusercontent.com/qmk/qmk_api/master/docs/architecture.svg) + +API Clients interact exclusively with the API service. This is where they submit jobs, check status, and download results. The API service inserts compile jobs into [Redis Queue](https://python-rq.org) and checks both RQ and S3 for the results of those jobs. + +Workers fetch new compile jobs from RQ, compile them, and then upload the source and the binary to an S3 compatible storage engine. + +# Workers + +QMK Compiler Workers are responsible for doing the actual building. When a worker pulls a job from RQ it does several things to complete that job: + +* Make a fresh qmk_firmware checkout +* Use the supplied layers and keyboard metadata to build a `keymap.c` +* Build the firmware +* Zip a copy of the source +* Upload the firmware, source zip, and a metadata file to S3. +* Report the status of the job to RQ + +# API Service + +The API service is a relatively simple Flask application. There are a few main views you should understand. + +## @app.route('/v1/compile', methods=['POST']) + +This is the main entrypoint for the API. A client's interaction starts here. The client POST's a JSON document describing their keyboard, and the API does some (very) basic validation of that JSON before submitting the compile job. + +## @app.route('/v1/compile/<string:job_id>', methods=['GET']) + +This is the most frequently called endpoint. It pulls the job details from redis, if they're still available, or the cached job details on S3 if they're not. + +## @app.route('/v1/compile/<string:job_id>/download', methods=['GET']) + +This method allows users to download the compiled firmware file. + +## @app.route('/v1/compile/<string:job_id>/source', methods=['GET']) + +This method allows users to download the source for their firmware. diff --git a/docs/api_docs.md b/docs/api_docs.md new file mode 100644 index 000000000000..28a7dd71da10 --- /dev/null +++ b/docs/api_docs.md @@ -0,0 +1,68 @@ +# QMK API + +This page describes using the QMK API. If you are an application developer you can use this API to compile firmware for any [QMK](https://qmk.fm) Keyboard. + +## Overview + +This service is an asynchronous API for compiling custom keymaps. You POST some JSON to the API, periodically check the status, and when your firmware has finished compiling you can download the resulting firmware and (if desired) source code for that firmware. + +#### Example JSON Payload: + +```json +{ + "keyboard": "clueboard/66/rev2", + "keymap": "my_awesome_keymap", + "layout": "LAYOUT_all", + "layers": [ + ["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_RO","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_MHEN","KC_SPC","KC_SPC","KC_HENK","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"], + ["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SLCK","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"], + ["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","RESET","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"] + ] +} +``` + +As you can see the payload describes all aspects of a keyboard necessary to create and generate a firmware. Each layer is a single list of QMK keycodes the same length as the keyboard's `LAYOUT` macro. If a keyboard supports mulitple `LAYOUT` macros you can specify which macro to use. + +## Submitting a Compile Job + +To compile your keymap into a firmware simply POST your JSON to the `/v1/compile` endpoint. In the following example we've placed the JSON payload into a file named `json_data`. + +``` +$ curl -H "Content-Type: application/json" -X POST -d "$(< json_data)" http://api.qmk.fm/v1/compile +{ + "enqueued": true, + "job_id": "ea1514b3-bdfc-4a7b-9b5c-08752684f7f6" +} +``` + +## Checking The Status + +After submitting your keymap you can check the status using a simple HTTP GET call: + +``` +$ curl http://api.qmk.fm/v1/compile/ea1514b3-bdfc-4a7b-9b5c-08752684f7f6 +{ + "created_at": "Sat, 19 Aug 2017 21:39:12 GMT", + "enqueued_at": "Sat, 19 Aug 2017 21:39:12 GMT", + "id": "f5f9b992-73b4-479b-8236-df1deb37c163", + "status": "running", + "result": null +} +``` + +This shows us that the job has made it through the queue and is currently running. There are 5 possible statuses: + +* **failed**: Something about the compiling service has broken. +* **finished**: The compilation is complete and you should check `result` to see the results. +* **queued**: The keymap is waiting for a compilation server to become available. +* **running**: The compilation is in progress and should be complete soon. +* **unknown**: A serious error has occurred and you should [file a bug](https://github.com/qmk/qmk_compiler/issues). + +## Examining Finished Results + +Once your compile job has finished you'll check the `result` key. The value of this key is a hash containing several key bits of information: + +* `firmware_binary_url`: A list of URLs for the the flashable firmware +* `firmware_keymap_url`: A list of URLs for the the `keymap.c` +* `firmware_source_url`: A list of URLs for the full firmware source code +* `output`: The stdout and stderr for this compile job. Errors will be found here. diff --git a/docs/api_overview.md b/docs/api_overview.md new file mode 100644 index 000000000000..91d317f06bc8 --- /dev/null +++ b/docs/api_overview.md @@ -0,0 +1,15 @@ +# QMK API + +The QMK API provides an asynchronous API that Web and GUI tools can use to compile arbitrary keymaps for any keyboard supported by [QMK](http://qmk.fm/). The stock keymap template supports all QMK keycodes that do not require supporting C code. Keyboard maintainers can supply their own custom templates to enable more functionality. + +## App Developers + +If you are an app developer interested in using this API in your application you should head over to [Using The API](api_docs.md). + +## Keyboard Maintainers + +If you would like to enhance your keyboard's support in the QMK Compiler API head over to the [Keyboard Support](reference_configurator_support.md) section. + +## Backend Developers + +If you are interested in working on the API itself you should start by setting up a [Development Environment](api_development_environment.md), then check out [Hacking On The API](api_development_overview.md). diff --git a/docs/becoming_a_qmk_collaborator.md b/docs/becoming_a_qmk_collaborator.md deleted file mode 100644 index 16ae0d569ec2..000000000000 --- a/docs/becoming_a_qmk_collaborator.md +++ /dev/null @@ -1,9 +0,0 @@ -# Becoming a QMK Collaborator - -A QMK collaborator is a keyboard maker or designer that is interested in helping QMK grow and fully support their keyboard(s), and encouraging their users and customers to submit features, ideas, and keymaps. We're always looking to add more keyboards and collaborators, but we ask that they fulfill these requirements: - -* **Have a PCB available for sale.** Unfortunately there's just too much variation and complications with handwired keyboards. -* **Maintain your keyboard in QMK.** This may just require an initial setup to get your keyboard working, but it could also include accommodating changes made to QMK's core that might break or render any custom code redundant. -* **Approve and merge keymap pull requests for your keyboard.** We like to encourage users to contribute their keymaps for others to see and work from when creating their own. - -If you feel you meet these requirements, shoot us an email at hello@qmk.fm with an introduction and some links to your keyboard! diff --git a/docs/cli.md b/docs/cli.md index 7c3effcc09ea..760fe1cdb569 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -1,24 +1,14 @@ -# QMK CLI +# QMK CLI :id=qmk-cli -This page describes how to setup and use the QMK CLI. - -# Overview +## Overview :id=overview The QMK CLI makes building and working with QMK keyboards easier. We have provided a number of commands to simplify and streamline tasks such as obtaining and compiling the QMK firmware, creating keymaps, and more. -* [Global CLI](#global-cli) -* [Local CLI](#local-cli) -* [CLI Commands](#cli-commands) - -# Requirements - -The CLI requires Python 3.5 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). +### Requirements :id=requirements -# Global CLI +The CLI requires Python 3.5 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). These are installed automatically when you install the QMK CLI. -QMK provides an installable CLI that can be used to setup your QMK build environment, work with QMK, and which makes working with multiple copies of `qmk_firmware` easier. We recommend installing and updating this periodically. - -## Install Using Homebrew (macOS, some Linux) +### Install Using Homebrew (macOS, some Linux) :id=install-using-homebrew If you have installed [Homebrew](https://brew.sh) you can tap and install QMK: @@ -29,7 +19,7 @@ export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware` qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment ``` -## Install Using easy_install or pip +### Install Using easy_install or pip :id=install-using-easy_install-or-pip If your system is not listed above you can install QMK manually. First ensure that you have python 3.5 (or later) installed and have installed pip. Then install QMK with this command: @@ -39,7 +29,7 @@ export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware` qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment ``` -## Packaging For Other Operating Systems +### Packaging For Other Operating Systems :id=packaging-for-other-operating-systems We are looking for people to create and maintain a `qmk` package for more operating systems. If you would like to create a package for your OS please follow these guidelines: @@ -47,269 +37,3 @@ We are looking for people to create and maintain a `qmk` package for more operat * Document why in a comment when you do deviate * Install using a virtualenv * Instruct the user to set the environment variable `QMK_HOME` to have the firmware source checked out somewhere other than `~/qmk_firmware`. - -# Local CLI - -If you do not want to use the global CLI there is a local CLI bundled with `qmk_firmware`. You can find it in `qmk_firmware/bin/qmk`. You can run the `qmk` command from any directory and it will always operate on that copy of `qmk_firmware`. - -**Example**: - -``` -$ ~/qmk_firmware/bin/qmk hello -Ψ Hello, World! -``` - -## Local CLI Limitations - -There are some limitations to the local CLI compared to the global CLI: - -* The local CLI does not support `qmk setup` or `qmk clone` -* The local CLI always operates on the same `qmk_firmware` tree, even if you have multiple repositories cloned. -* The local CLI does not run in a virtualenv, so it's possible that dependencies will conflict - -# CLI Commands - -## `qmk cformat` - -This command formats C code using clang-format. - -Run it with no arguments to format all core code that has been changed. Default checks `origin/master` with `git diff`, branch can be changed using `-b ` - -Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files. - -**Usage for specified files**: - -``` -qmk cformat [file1] [file2] [...] [fileN] -``` - -**Usage for all core files**: - -``` -qmk cformat -a -``` - -**Usage for only changed files against origin/master**: - -``` -qmk cformat -``` - -**Usage for only changed files against branch_name**: - -``` -qmk cformat -b branch_name -``` - -## `qmk compile` - -This command allows you to compile firmware from any directory. You can compile JSON exports from , compile keymaps in the repo, or compile the keyboard in the current working directory. - -**Usage for Configurator Exports**: - -``` -qmk compile -``` - -**Usage for Keymaps**: - -``` -qmk compile -kb -km -``` - -**Usage in Keyboard Directory**: - -Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap ` -``` -qmk compile -``` - -**Example**: -``` -$ qmk config compile.keymap=default -$ cd ~/qmk_firmware/keyboards/planck/rev6 -$ qmk compile -Ψ Compiling keymap with make planck/rev6:default -... -``` -or with optional keymap argument - -``` -$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4 -$ qmk compile -km 66_iso -Ψ Compiling keymap with make clueboard/66/rev4:66_iso -... -``` -or in keymap directory - -``` -$ cd ~/qmk_firmware/keyboards/gh60/satan/keymaps/colemak -$ qmk compile -Ψ Compiling keymap with make make gh60/satan:colemak -... -``` - -**Usage in Layout Directory**: - -Must be under `qmk_firmware/layouts/`, and in a keymap folder. -``` -qmk compile -kb -``` - -**Example**: -``` -$ cd ~/qmk_firmware/layouts/community/60_ansi/mechmerlin-ansi -$ qmk compile -kb dz60 -Ψ Compiling keymap with make dz60:mechmerlin-ansi -... -``` - -## `qmk flash` - -This command is similar to `qmk compile`, but can also target a bootloader. The bootloader is optional, and is set to `:flash` by default. -To specify a different bootloader, use `-bl `. Visit -for more details of the available bootloaders. - -**Usage for Configurator Exports**: - -``` -qmk flash -bl -``` - -**Usage for Keymaps**: - -``` -qmk flash -kb -km -bl -``` - -**Listing the Bootloaders** - -``` -qmk flash -b -``` - -## `qmk config` - -This command lets you configure the behavior of QMK. For the full `qmk config` documentation see [CLI Configuration](cli_configuration.md). - -**Usage**: - -``` -qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] -``` - -## `qmk docs` - -This command starts a local HTTP server which you can use for browsing or improving the docs. Default port is 8936. - -**Usage**: - -``` -qmk docs [-p PORT] -``` - -## `qmk doctor` - -This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. - -**Usage**: - -``` -qmk doctor [-y] [-n] -``` - -**Examples**: - -Check your environment for problems and prompt to fix them: - - qmk doctor - -Check your environment and automatically fix any problems found: - - qmk doctor -y - -Check your environment and report problems only: - - qmk doctor -n - -## `qmk json-keymap` - -Creates a keymap.c from a QMK Configurator export. - -**Usage**: - -``` -qmk json-keymap [-o OUTPUT] filename -``` - -## `qmk kle2json` - -This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite. - -**Usage**: - -``` -qmk kle2json [-f] -``` - -**Examples**: - -``` -$ qmk kle2json kle.txt -☒ File info.json already exists, use -f or --force to overwrite. -``` - -``` -$ qmk kle2json -f kle.txt -f -Ψ Wrote out to info.json -``` - -## `qmk list-keyboards` - -This command lists all the keyboards currently defined in `qmk_firmware` - -**Usage**: - -``` -qmk list-keyboards -``` - -## `qmk list-keymaps` - -This command lists all the keymaps for a specified keyboard (and revision). - -**Usage**: - -``` -qmk list-keymaps -kb planck/ez -``` - -## `qmk new-keymap` - -This command creates a new keymap based on a keyboard's existing default keymap. - -**Usage**: - -``` -qmk new-keymap [-kb KEYBOARD] [-km KEYMAP] -``` - -## `qmk pyformat` - -This command formats python code in `qmk_firmware`. - -**Usage**: - -``` -qmk pyformat -``` - -## `qmk pytest` - -This command runs the python test suite. If you make changes to python code you should ensure this runs successfully. - -**Usage**: - -``` -qmk pytest -``` diff --git a/docs/cli_commands.md b/docs/cli_commands.md new file mode 100644 index 000000000000..eb5362bd2953 --- /dev/null +++ b/docs/cli_commands.md @@ -0,0 +1,253 @@ +# QMK CLI Commands + +# CLI Commands + +## `qmk cformat` + +This command formats C code using clang-format. + +Run it with no arguments to format all core code that has been changed. Default checks `origin/master` with `git diff`, branch can be changed using `-b ` + +Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files. + +**Usage for specified files**: + +``` +qmk cformat [file1] [file2] [...] [fileN] +``` + +**Usage for all core files**: + +``` +qmk cformat -a +``` + +**Usage for only changed files against origin/master**: + +``` +qmk cformat +``` + +**Usage for only changed files against branch_name**: + +``` +qmk cformat -b branch_name +``` + +## `qmk compile` + +This command allows you to compile firmware from any directory. You can compile JSON exports from , compile keymaps in the repo, or compile the keyboard in the current working directory. + +**Usage for Configurator Exports**: + +``` +qmk compile +``` + +**Usage for Keymaps**: + +``` +qmk compile -kb -km +``` + +**Usage in Keyboard Directory**: + +Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap ` +``` +qmk compile +``` + +**Usage for building all keyboards that support a specific keymap**: + +``` +qmk compile -kb all -km +``` + +**Example**: +``` +$ qmk config compile.keymap=default +$ cd ~/qmk_firmware/keyboards/planck/rev6 +$ qmk compile +Ψ Compiling keymap with make planck/rev6:default +... +``` +or with optional keymap argument + +``` +$ cd ~/qmk_firmware/keyboards/clueboard/66/rev4 +$ qmk compile -km 66_iso +Ψ Compiling keymap with make clueboard/66/rev4:66_iso +... +``` +or in keymap directory + +``` +$ cd ~/qmk_firmware/keyboards/gh60/satan/keymaps/colemak +$ qmk compile +Ψ Compiling keymap with make make gh60/satan:colemak +... +``` + +**Usage in Layout Directory**: + +Must be under `qmk_firmware/layouts/`, and in a keymap folder. +``` +qmk compile -kb +``` + +**Example**: +``` +$ cd ~/qmk_firmware/layouts/community/60_ansi/mechmerlin-ansi +$ qmk compile -kb dz60 +Ψ Compiling keymap with make dz60:mechmerlin-ansi +... +``` + +## `qmk flash` + +This command is similar to `qmk compile`, but can also target a bootloader. The bootloader is optional, and is set to `:flash` by default. +To specify a different bootloader, use `-bl `. Visit the [Flashing Firmware](flashing.md) guide for more details of the available bootloaders. + +**Usage for Configurator Exports**: + +``` +qmk flash -bl +``` + +**Usage for Keymaps**: + +``` +qmk flash -kb -km -bl +``` + +**Listing the Bootloaders** + +``` +qmk flash -b +``` + +## `qmk config` + +This command lets you configure the behavior of QMK. For the full `qmk config` documentation see [CLI Configuration](cli_configuration.md). + +**Usage**: + +``` +qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] +``` + +## `qmk docs` + +This command starts a local HTTP server which you can use for browsing or improving the docs. Default port is 8936. + +**Usage**: + +``` +qmk docs [-p PORT] +``` + +## `qmk doctor` + +This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. + +**Usage**: + +``` +qmk doctor [-y] [-n] +``` + +**Examples**: + +Check your environment for problems and prompt to fix them: + + qmk doctor + +Check your environment and automatically fix any problems found: + + qmk doctor -y + +Check your environment and report problems only: + + qmk doctor -n + +## `qmk json2c` + +Creates a keymap.c from a QMK Configurator export. + +**Usage**: + +``` +qmk json2c [-o OUTPUT] filename +``` + +## `qmk kle2json` + +This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite. + +**Usage**: + +``` +qmk kle2json [-f] +``` + +**Examples**: + +``` +$ qmk kle2json kle.txt +☒ File info.json already exists, use -f or --force to overwrite. +``` + +``` +$ qmk kle2json -f kle.txt -f +Ψ Wrote out to info.json +``` + +## `qmk list-keyboards` + +This command lists all the keyboards currently defined in `qmk_firmware` + +**Usage**: + +``` +qmk list-keyboards +``` + +## `qmk list-keymaps` + +This command lists all the keymaps for a specified keyboard (and revision). + +**Usage**: + +``` +qmk list-keymaps -kb planck/ez +``` + +## `qmk new-keymap` + +This command creates a new keymap based on a keyboard's existing default keymap. + +**Usage**: + +``` +qmk new-keymap [-kb KEYBOARD] [-km KEYMAP] +``` + +## `qmk pyformat` + +This command formats python code in `qmk_firmware`. + +**Usage**: + +``` +qmk pyformat +``` + +## `qmk pytest` + +This command runs the python test suite. If you make changes to python code you should ensure this runs successfully. + +**Usage**: + +``` +qmk pytest +``` diff --git a/docs/cli_configuration.md b/docs/cli_configuration.md index ad9ff291c811..1196ab669d1a 100644 --- a/docs/cli_configuration.md +++ b/docs/cli_configuration.md @@ -4,7 +4,7 @@ This document explains how `qmk config` works. # Introduction -Configuration for QMK CLI is a key/value system. Each key consists of a subcommand and an argument name separated by a period. This allows for a straightforward and direct translation between config keys and the arguments they set. +Configuration for the QMK CLI is a key/value system. Each key consists of a subcommand and an argument name separated by a period. This allows for a straightforward and direct translation between config keys and the arguments they set. ## Simple Example diff --git a/docs/config_options.md b/docs/config_options.md index df4b67dc1604..661cfccce6de 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -136,22 +136,22 @@ If you define these options you will enable the associated feature, which may in * enables handling for per key `TAPPING_TERM` settings * `#define RETRO_TAPPING` * tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release - * See [Retro Tapping](feature_advanced_keycodes.md#retro-tapping) for details + * See [Retro Tapping](tap_hold.md#retro-tapping) for details * `#define TAPPING_TOGGLE 2` * how many taps before triggering the toggle * `#define PERMISSIVE_HOLD` * makes tap and hold keys trigger the hold if another key is pressed before releasing, even if it hasn't hit the `TAPPING_TERM` - * See [Permissive Hold](feature_advanced_keycodes.md#permissive-hold) for details + * See [Permissive Hold](tap_hold.md#permissive-hold) for details * `#define PERMISSIVE_HOLD_PER_KEY` * enabled handling for per key `PERMISSIVE_HOLD` settings * `#define IGNORE_MOD_TAP_INTERRUPT` * makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys. - * See [Mod tap interrupt](feature_advanced_keycodes.md#ignore-mod-tap-interrupt) for details + * 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 [Hold after tap](feature_advanced_keycodes.md#tapping-force-hold) + * 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 @@ -190,6 +190,8 @@ If you define these options you will enable the associated feature, which may in * pin the DI on the WS2812 is hooked-up to * `#define RGBLIGHT_ANIMATIONS` * run RGB animations +* `#define RGBLIGHT_LAYERS` + * Lets you define [lighting layers](feature_rgblight.md) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state. * `#define RGBLED_NUM 12` * number of LEDs * `#define RGBLIGHT_SPLIT` @@ -335,7 +337,7 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i * `bootloadHID` * `USBasp` -## Feature Options +## Feature Options :id=feature-options Use these to enable or disable building certain features. The more you have enabled the bigger your firmware will be, and you run the risk of building a firmware too large for your MCU. diff --git a/docs/configurator_step_by_step.md b/docs/configurator_step_by_step.md new file mode 100644 index 000000000000..aee1d4e1f622 --- /dev/null +++ b/docs/configurator_step_by_step.md @@ -0,0 +1,58 @@ +# QMK Configurator: Step by Step + +This page describes the steps for building your firmware in QMK Configurator. + +## Step 1: Select Your Keyboard + +Click the drop down box and select the keyboard you want to create a keymap for. + +?> If your keyboard has several versions, make sure you select the correct one. + +I'll say that again because it's important: + +!> **MAKE SURE YOU SELECT THE RIGHT VERSION!** + +If your keyboard has been advertised to be powered by QMK but is not in the list, chances are a developer hasn't gotten to it yet or we haven't had a chance to merge it in yet. File an issue at [qmk_firmware](https://github.com/qmk/qmk_firmware/issues) requesting to support that particular keyboard, if there is no active [Pull Request](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) for it. There are also QMK powered keyboards that are in their manufacturer's own github accounts. Double check for that as well. + +## Step 2: Select Your Keyboard Layout + +Choose the layout that best represents the keymap you want to create. Some keyboards do not have enough layouts or correct layouts defined yet. They will be supported in the future. + +!> Sometimes there isn't a layout that supports your exact build. In that case select `LAYOUT_all`. + +## Step 3: Name Your Keymap + +Call this keymap what you want. + +?> If you are running into issues when compiling, it may be worth changing this name, as it may already exist in the QMK Firmware repo. + +## Step 4: Define Your Keymap + +Keycode Entry is accomplished in one of 3 ways: + +1. Drag and drop +2. Clicking on an empty spot on the layout, then clicking the keycode you desire +3. Clicking on an empty spot on the layout, then pressing the physical key on your keyboard + +?> Hover your mouse over a key and a short blurb will tell you what that keycode does. For a more verbose description please see: + +* [Basic Keycode Reference](keycodes_basic.md) +* [Advanced Keycode Reference](feature_advanced_keycodes.md) + +!> If your selected layout doesn't match your physical build leave the unused keys blank. If you're not sure which key is in use, for example you have a one backspace key but `LAYOUT_all` has 2 keys, put the same keycode in both locations. + +## Step 5: Save Your Keymap for Future Changes + +When you're satisfied with your keymap or just want to work on it later, press the `Export Keymap` button. It will save your keymap to your computer. You can then load this .json file in the future by pressing the `Import Keymap` button. + +!> **CAUTION:** This is not the same type of .json file used for kbfirmware.com or any other tool. If you try to use this for those tools, or the .json from those tools with QMK Configurator, you will encounter problems. + +## Step 6: Compile Your Firmware File + +Press the green `Compile` button. + +When the compilation is done, you will be able to press the green `Download Firmware` button. + +## Next steps: Flashing Your Keyboard + +Please refer to [Flashing Firmware](newbs_flashing.md). diff --git a/docs/configurator_troubleshooting.md b/docs/configurator_troubleshooting.md new file mode 100644 index 000000000000..80b9713b64ea --- /dev/null +++ b/docs/configurator_troubleshooting.md @@ -0,0 +1,26 @@ +# Configurator Troubleshooting + +## My .json file is not working + +If the .json file was generated with QMK Configurator, congratulations you have stumbled upon a bug. File an issue at [qmk_configurator](https://github.com/qmk/qmk_configurator/issues). + +If not... how did you miss the big bold message at the top saying not to use other .json files? + +## There are extra spaces in my layout? What do I do? + +If you're referring to having three spots for space bar, the best course of action is to just fill them all with Space. The same can be done for Backspace and Shift keys. + +## What is the keycode for... + +Please see: + +* [Basic Keycode Reference](keycodes_basic.md) +* [Advanced Keycode Reference](feature_advanced_keycodes.md) + +## It won't compile + +Please double check the other layers of your keymap to make sure there are no random keys present. + +## Problems and Bugs + +We are always accepting customer requests and bug reports. Please file them at [qmk_configurator](https://github.com/qmk/qmk_configurator/issues). diff --git a/docs/contributing.md b/docs/contributing.md index c4d5057a07a0..f325566fd063 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -101,7 +101,7 @@ enum my_keycodes { }; ``` -### Previewing the Documentation +### Previewing the Documentation :id=previewing-the-documentation Before opening a pull request, you can preview your changes if you have set up the development environment by running this command from the `qmk_firmware/` folder: diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index 9c8f89ae18d9..84ae589ed6c3 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md @@ -4,7 +4,7 @@ For a lot of people a custom keyboard is about more than sending button presses This page does not assume any special knowledge about QMK, but reading [Understanding QMK](understanding_qmk.md) will help you understand what is going on at a more fundamental level. -## A Word on Core vs Keyboards vs Keymap +## A Word on Core vs Keyboards vs Keymap :id=a-word-on-core-vs-keyboards-vs-keymap We have structured QMK as a hierarchy: @@ -34,7 +34,7 @@ enum my_keycodes { }; ``` -## Programming the Behavior of Any Keycode +## Programming the Behavior of Any Keycode :id=programming-the-behavior-of-any-keycode When you want to override the behavior of an existing key, or define the behavior for a new key, you should use the `process_record_kb()` and `process_record_user()` functions. These are called by QMK during key processing before the actual key event is handled. If these functions return `true` QMK will process the keycodes as usual. That can be handy for extending the functionality of a key rather than replacing it. If these functions return `false` QMK will skip the normal key handling, and it will be up to you to send any key up or down events that are required. @@ -313,7 +313,7 @@ void suspend_wakeup_init_user(void) { * Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)` * Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)` -# Layer Change Code +# Layer Change Code :id=layer-change-code This runs code every time that the layers get changed. This can be useful for layer indication, or custom layer handling. diff --git a/docs/de/_summary.md b/docs/de/_summary.md index f3ce806baa23..a894420a2b53 100644 --- a/docs/de/_summary.md +++ b/docs/de/_summary.md @@ -77,7 +77,7 @@ * [Macros](de/feature_macros.md) * [Mouse Keys](de/feature_mouse_keys.md) * [OLED Driver](de/feature_oled_driver.md) - * [One Shot Keys](de/feature_advanced_keycodes.md#one-shot-keys) + * [One Shot Keys](de/one_shot_keys.md) * [Pointing Device](de/feature_pointing_device.md) * [PS/2 Mouse](de/feature_ps2_mouse.md) * [RGB Lighting](de/feature_rgblight.md) @@ -108,7 +108,7 @@ * Andere Themen * [Eclipse mit QMK](de/other_eclipse.md) * [VSCode mit QMK](de/other_vscode.md) - * [Support](de/support.md) + * [Support](de/getting_started_getting_help.md) * [Übersetzungen](de/translating.md) * QMK Internals (In Progress) diff --git a/docs/documentation_templates.md b/docs/documentation_templates.md index 85d3893b71ac..8df25590c4fe 100644 --- a/docs/documentation_templates.md +++ b/docs/documentation_templates.md @@ -2,7 +2,7 @@ This page documents the templates you should use when submitting new Keymaps and Keyboards to QMK. -## Keymap `readme.md` Template +## Keymap `readme.md` Template :id=keyboard-readmemd-template Most keymaps have an image depicting the layout. You can use [Keyboard Layout Editor](http://keyboard-layout-editor.com) to create an image. Upload it to [Imgur](http://imgur.com) or another hosting service, please do not include images in your Pull Request. diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md index dd12d8ec7b08..5a91a7c2dabf 100644 --- a/docs/eeprom_driver.md +++ b/docs/eeprom_driver.md @@ -2,14 +2,16 @@ The EEPROM driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present. -Driver | Description ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -`EEPROM_DRIVER = vendor` | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. Other chips will generally act as "transient" below. -`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below. -`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost. +Driver | Description +-----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +`EEPROM_DRIVER = vendor` (default) | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. STM32L0xx and STM32L1xx will use the onboard dedicated true EEPROM. Other chips will generally act as "transient" below. +`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below. +`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost. ## Vendor Driver Configuration +!> Resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used. + No configurable options are available. ## I2C Driver Configuration diff --git a/docs/es/_summary.md b/docs/es/_summary.md index 03bf05ba8b58..7dffea7d2b0f 100644 --- a/docs/es/_summary.md +++ b/docs/es/_summary.md @@ -77,7 +77,7 @@ * [Macros](es/feature_macros.md) * [Teclas del ratón](es/feature_mouse_keys.md) * [Driver OLED](es/feature_oled_driver.md) - * [Teclas One Shot](es/feature_advanced_keycodes.md#one-shot-keys) + * [Teclas One Shot](es/one_shot_keys.md) * [Dispositivo de apuntado](es/feature_pointing_device.md) * [Ratón PS/2](es/feature_ps2_mouse.md) * [Iluminación RGB](es/feature_rgblight.md) @@ -108,7 +108,7 @@ * Otros temas * [Usando Eclipse con QMK](es/other_eclipse.md) * [Usando VSCode con QMK](es/other_vscode.md) - * [Soporte](es/support.md) + * [Soporte](es/getting_started_getting_help.md) * [Cómo añadir traducciones](es/translating.md) * QMK Internals (En progreso) diff --git a/docs/es/becoming_a_qmk_collaborator.md b/docs/es/becoming_a_qmk_collaborator.md deleted file mode 100644 index f88846df24e4..000000000000 --- a/docs/es/becoming_a_qmk_collaborator.md +++ /dev/null @@ -1,9 +0,0 @@ -# Llegar a ser un colaborador QMK - -Un colaborador QMK es un maker o diseñador de teclados que tiene interés en ayudar a QMK a crecer y mantener sus teclado(s), y alentar a los usuarios y clientes a presentar herramientas, ideas, y keymaps. Siempre procuramos agregar más teclados y colaboradores, pero pedimos que cumplan los siguientes requisitos: - -* **Tener un PCB disponible a la venta.** Desafortunadamente, hay demasiada variación y complicaciones con teclados cableados a mano. -* **Realizar el mantenimiento de tu teclado en QMK.** Este podría requirir un setup inicial para hacer que tu teclado funcione, pero también podría incluir adaptarse a cambios hecho al base de QMK que podrían descomponer o rendir código superfluo. -* **Aprobar e incorporar pull requests de keymaps para tu teclado.** Nos gusta alentar a los usuarios a contribuir sus keymaps para que otros los vean y los puedan usar para crear sus propios. - -Si sientes que cumples los requisitos, ¡mándanos un email a hello@qmk.fm con una introducción y algunos enlaces para tu teclado! diff --git a/docs/es/newbs_building_firmware_configurator.md b/docs/es/newbs_building_firmware_configurator.md index a25734324018..9333159c2cb4 100644 --- a/docs/es/newbs_building_firmware_configurator.md +++ b/docs/es/newbs_building_firmware_configurator.md @@ -4,7 +4,7 @@ El [Configurador QMK](https://config.qmk.fm) es un entorno gráfico online que g ?> **Por favor sigue estos pasos en orden.** -Ve el [Video tutorial](https://youtu.be/tx54jkRC9ZY) +Ve el [Video tutorial](https://www.youtube.com/watch?v=-imgglzDMdY) El Configurador QMK functiona mejor con Chrome/Firefox. diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index 506f57a72b46..000000000000 --- a/docs/faq.md +++ /dev/null @@ -1,6 +0,0 @@ -# Frequently Asked Questions - -* [General](faq_general.md) -* [Building or Compiling QMK](faq_build.md) -* [Debugging and Troubleshooting QMK](faq_debug.md) -* [Keymap](faq_keymap.md) diff --git a/docs/faq_general.md b/docs/faq_general.md index f14272ede8f0..8e9771cbcd6a 100644 --- a/docs/faq_general.md +++ b/docs/faq_general.md @@ -4,6 +4,44 @@ [QMK](https://github.com/qmk), short for Quantum Mechanical Keyboard, is a group of people building tools for custom keyboards. We started with the [QMK firmware](https://github.com/qmk/qmk_firmware), a heavily modified fork of [TMK](https://github.com/tmk/tmk_keyboard). +## I don't know where to start! + +If this is the case, then you should start with our [Newbs Guide](newbs.md). There is a lot of great info there, and that should cover everything you need to get started. + +If that's an issue, hop onto the [QMK Configurator](https://config.qmk.fm), as that will handle a majority of what you need there. + +## How can I flash the firmware I built? + +First, head to the [Compiling/Flashing FAQ Page](faq_build.md). There is a good deal of info there, and you'll find a bunch of solutions to common issues there. + +## What if I have an issue that isn't covered here? + +Okay, that's fine. Then please check the [open issues in our GitHub](https://github.com/qmk/qmk_firmware/issues) to see if somebody is experiencing the same thing (make sure it's not just similar, but actually the same). + +If you can't find anything, then please open a [new issue](https://github.com/qmk/qmk_firmware/issues/new)! + +## What if I found a bug? + +Then please open an [issue](https://github.com/qmk/qmk_firmware/issues/new), and if you know how to fix it, open up a Pull Request on GitHub with the fix. + +## But `git` and `GitHub` are intimidating! + +Don't worry, we have some pretty nice [Guidelines](newbs_git_best_practices.md) on how to start using `git` and GitHub to make things easier to develop. + +Additionally, you can find additional `git` and GitHub related links [here](newbs_learn_more_resources.md). + +## I have a Keyboard that I want to add support for + +Awesome! Open up a Pull Request for it. We'll review the code, and merge it! + +### What if I want to do brand it with `QMK`? + +That's amazing! We would love to assist you with that! + +In fact, we have a [whole page](https://qmk.fm/powered/) dedicated to adding QMK Branding to your page and keyboard. This covers pretty much everything you need (knowledge and images) to officially support QMK. + +If you have any questions about this, open an issue or head to [Discord](https://discord.gg/Uq7gcHh). + ## What Differences Are There Between QMK and TMK? TMK was originally designed and implemented by [Jun Wako](https://github.com/tmk). QMK started as [Jack Humbert](https://github.com/jackhumbert)'s fork of TMK for the Planck. After a while Jack's fork had diverged quite a bit from TMK, and in 2015 Jack decided to rename his fork to QMK. diff --git a/docs/faq_keymap.md b/docs/faq_keymap.md index 2d00e8bef958..d1d9b9196495 100644 --- a/docs/faq_keymap.md +++ b/docs/faq_keymap.md @@ -14,6 +14,17 @@ There are 3 standard keyboard layouts in use around the world- ANSI, ISO, and JI ![Keyboard Layout Image](https://i.imgur.com/5wsh5wM.png) +## How Can I Make Custom Names For Complex Keycodes? + +Sometimes, for readability's sake, it's useful to define custom names for some keycodes. People often define custom names using `#define`. For example: + +```c +#define FN_CAPS LT(_FL, KC_CAPSLOCK) +#define ALT_TAB LALT(KC_TAB) +``` + +This will allow you to use `FN_CAPS` and `ALT_TAB` in your keymap, keeping it more readable. + ## Some Of My Keys Are Swapped Or Not Working QMK has two features, Bootmagic and Command, which allow you to change the behavior of your keyboard on the fly. This includes, but is not limited to, swapping Ctrl/Caps, disabling Gui, swapping Alt/Gui, swapping Backspace/Backslash, disabling all keys, and other behavioral modifications. diff --git a/docs/feature_advanced_keycodes.md b/docs/feature_advanced_keycodes.md index 8c3449460573..b2abe5dae083 100644 --- a/docs/feature_advanced_keycodes.md +++ b/docs/feature_advanced_keycodes.md @@ -1,62 +1,4 @@ -# Advanced Keycodes - -Your keymap can include keycodes that are more advanced than normal, for example keys that switch layers or send modifiers when held, but send regular keycodes when tapped. This page documents the functions that are available to you. - -## Assigning Custom Names - -People often define custom names using `#define`. For example: - -```c -#define FN_CAPS LT(_FL, KC_CAPSLOCK) -#define ALT_TAB LALT(KC_TAB) -``` - -This will allow you to use `FN_CAPS` and `ALT_TAB` in your keymap, keeping it more readable. - -## Caveats - -Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Modifiers specified as part of a Layer Tap or Mod Tap's keycode will be ignored. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this. - -Additionally, if at least one right-handed modifier is specified in a Mod Tap or Layer Tap, it will cause all modifiers specified to become right-handed, so it is not possible to mix and match the two. - -# Switching and Toggling Layers - -These functions allow you to activate layers in various ways. Note that layers are not generally independent layouts -- multiple layers can be activated at once, and it's typical for layers to use `KC_TRNS` to allow keypresses to pass through to lower layers. For a detailed explanation of layers, see [Keymap Overview](keymap.md#keymap-and-layers). When using momentary layer switching with MO(), LM(), TT(), or LT(), make sure to leave the key on the above layers transparent or it may not work as intended. - -* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).) -* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated. -* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`. -* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15. -* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](#one-shot-keys) for details and additional functionality. -* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa -* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed). -* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps. - -# Working with Layers - -Care must be taken when switching layers, it's possible to lock yourself into a layer with no way to deactivate that layer (without unplugging your keyboard.) We've created some guidelines to help users avoid the most common problems. - -## Beginners - -If you are just getting started with QMK you will want to keep everything simple. Follow these guidelines when setting up your layers: - -* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number). -* Arrange your layers in a "tree" layout, with layer 0 as the root. Do not try to enter the same layer from more than one other layer. -* In a layer's keymap, only reference higher-numbered layers. Because layers are processed from the highest-numbered (topmost) active layer down, modifying the state of lower layers can be tricky and error-prone. - -## Intermediate Users - -Sometimes you need more than one base layer. For example, if you want to switch between QWERTY and Dvorak, switch between layouts for different countries, or switch your layout for different videogames. Your base layers should always be the lowest numbered layers. When you have multiple base layers you should always treat them as mutually exclusive. When one base layer is on the others are off. - -## Advanced Users - -Once you have a good feel for how layers work and what you can do, you can get more creative. The rules listed in the beginner section will help you be successful by avoiding some of the tricker details but they can be constraining, especially for ultra-compact keyboard users. Understanding how layers work will allow you to use them in more advanced ways. - -Layers stack on top of each other in numerical order. When determining what a keypress does, QMK scans the layers from the top down, stopping when it reaches the first active layer that is not set to `KC_TRNS`. As a result if you activate a layer that is numerically lower than your current layer, and your current layer (or another layer that is active and higher than your target layer) has something other than `KC_TRNS`, that is the key that will be sent, not the key on the layer you just activated. This is the cause of most people's "why doesn't my layer get switched" problem. - -Sometimes, you might want to switch between layers in a macro or as part of a tap dance routine. `layer_on` activates a layer, and `layer_off` deactivates it. More layer-related functions can be found in [action_layer.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/action_layer.h). - -# Modifier Keys +# Modifier Keys :id=modifier-keys These allow you to combine a modifier with a keycode. When pressed, the keydown event for the modifier, then `kc` will be sent. On release, the keyup event for `kc`, then the modifier will be sent. @@ -78,308 +20,22 @@ These allow you to combine a modifier with a keycode. When pressed, the keydown You can also chain them, for example `LCTL(LALT(KC_DEL))` makes a key that sends Control+Alt+Delete with a single keypress. -# Mod-Tap - -The Mod-Tap key `MT(mod, kc)` acts like a modifier when held, and a regular keycode when tapped. In other words, you can have a key that sends Escape when you tap it, but functions as a Control or Shift key when you hold it down. - -The modifiers this keycode and `OSM()` accept are prefixed with `MOD_`, not `KC_`: - -|Modifier |Description | -|----------|----------------------------------------| -|`MOD_LCTL`|Left Control | -|`MOD_LSFT`|Left Shift | -|`MOD_LALT`|Left Alt | -|`MOD_LGUI`|Left GUI (Windows/Command/Meta key) | -|`MOD_RCTL`|Right Control | -|`MOD_RSFT`|Right Shift | -|`MOD_RALT`|Right Alt (AltGr) | -|`MOD_RGUI`|Right GUI (Windows/Command/Meta key) | -|`MOD_HYPR`|Hyper (Left Control, Shift, Alt and GUI)| -|`MOD_MEH` |Meh (Left Control, Shift, and Alt) | - -You can combine these by ORing them together like so: - -```c -MT(MOD_LCTL | MOD_LSFT, KC_ESC) -``` - -This key would activate Left Control and Left Shift when held, and send Escape when tapped. - -For convenience, QMK includes some Mod-Tap shortcuts to make common combinations more compact in your keymap: - -|Key |Aliases |Description | -|------------|-----------------------------------------------------------------|-------------------------------------------------------| -|`LCTL_T(kc)`|`CTL_T(kc)` |Left Control when held, `kc` when tapped | -|`LSFT_T(kc)`|`SFT_T(kc)` |Left Shift when held, `kc` when tapped | -|`LALT_T(kc)`|`ALT_T(kc)` |Left Alt when held, `kc` when tapped | -|`LGUI_T(kc)`|`LCMD_T(kc)`, `LWIN_T(kc)`, `GUI_T(kc)`, `CMD_T(kc)`, `WIN_T(kc)`|Left GUI when held, `kc` when tapped | -|`RCTL_T(kc)`| |Right Control when held, `kc` when tapped | -|`RSFT_T(kc)`| |Right Shift when held, `kc` when tapped | -|`RALT_T(kc)`|`ALGR_T(kc)` |Right Alt when held, `kc` when tapped | -|`RGUI_T(kc)`|`RCMD_T(kc)`, `RWIN_T(kc)` |Right GUI when held, `kc` when tapped | -|`SGUI_T(kc)`|`SCMD_T(kc)`, `SWIN_T(kc)` |Left Shift and GUI when held, `kc` when tapped | -|`LCA_T(kc)` | |Left Control and Alt when held, `kc` when tapped | -|`LCAG_T(kc)`| |Left Control, Alt and GUI when held, `kc` when tapped | -|`RCAG_T(kc)`| |Right Control, Alt and GUI when held, `kc` when tapped | -|`C_S_T(kc)` | |Left Control and Shift when held, `kc` when tapped | -|`MEH_T(kc)` | |Left Control, Shift and Alt when held, `kc` when tapped| -|`HYPR_T(kc)`|`ALL_T(kc)` |Left Control, Shift, Alt and GUI when held, `kc` when tapped - more info [here](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)| - -## Caveats - -Unfortunately, these keycodes cannot be used in Mod-Taps or Layer-Taps, since any modifiers specified in the keycode are ignored. - -Additionally, you may run into issues when using Remote Desktop Connection on Windows. Because these codes send shift very fast, Remote Desktop may miss the codes. - -To fix this, open Remote Desktop Connection, click on "Show Options", open the the "Local Resources" tab. In the keyboard section, change the drop down to "On this Computer". This will fix the issue, and allow the characters to work correctly. - -# One Shot Keys - -One shot keys are keys that remain active until the next key is pressed, and then are released. This allows you to type keyboard combinations without pressing more than one key at a time. These keys are usually called "Sticky keys" or "Dead keys". - -For example, if you define a key as `OSM(MOD_LSFT)`, you can type a capital A character by first pressing and releasing shift, and then pressing and releasing A. Your computer will see the shift key being held the moment shift is pressed, and it will see the shift key being released immediately after A is released. - -One shot keys also work as normal modifiers. If you hold down a one shot key and type other keys, your one shot will be released immediately after you let go of the key. - -Additionally, hitting keys five times in a short period will lock that key. This applies for both One Shot Modifiers and One Shot Layers, and is controlled by the `ONESHOT_TAP_TOGGLE` define. - -You can control the behavior of one shot keys by defining these in `config.h`: - -```c -#define ONESHOT_TAP_TOGGLE 5 /* Tapping this number of times holds the key until tapped once again. */ -#define ONESHOT_TIMEOUT 5000 /* Time (in ms) before the one shot key is released */ -``` - -* `OSM(mod)` - Momentarily hold down *mod*. You must use the `MOD_*` keycodes as shown in [Mod Tap](#mod-tap), not the `KC_*` codes. -* `OSL(layer)` - momentary switch to *layer*. - -Sometimes, you want to activate a one-shot key as part of a macro or tap dance routine. - -For one shot layers, you need to call `set_oneshot_layer(LAYER, ONESHOT_START)` on key down, and `clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED)` on key up. If you want to cancel the oneshot, call `reset_oneshot_layer()`. - -For one shot mods, you need to call `set_oneshot_mods(MOD)` to set it, or `clear_oneshot_mods()` to cancel it. - -!> If you're having issues with OSM translating over Remote Desktop Connection, this can be fixed by opening the settings, going to the "Local Resources" tap, and in the keyboard section, change the drop down to "On this Computer". This will fix the issue and allow OSM to function properly over Remote Desktop. - -## Callbacks - -When you'd like to perform custom logic when pressing a one shot key, there are several callbacks you can choose to implement. You could indicate changes in one shot keys by flashing an LED or making a sound, for example. - -There is a callback for `OSM(mod)`. It is called whenever the state of any one shot modifier key is changed: when it toggles on, but also when it is toggled off. You can use it like this: - -```c -void oneshot_mods_changed_user(uint8_t mods) { - if (mods & MOD_MASK_SHIFT) { - println("Oneshot mods SHIFT"); - } - if (mods & MOD_MASK_CTRL) { - println("Oneshot mods CTRL"); - } - if (mods & MOD_MASK_ALT) { - println("Oneshot mods ALT"); - } - if (mods & MOD_MASK_GUI) { - println("Oneshot mods GUI"); - } - if (!mods) { - println("Oneshot mods off"); - } -} -``` - -The `mods` argument contains the active mods after the change, so it reflects the current state. - -When you use One Shot Tap Toggle (by adding `#define ONESHOT_TAP_TOGGLE 2` in your `config.h` file), you may lock a modifier key by pressing it the specified amount of times. There's a callback for that, too: - -```c -void oneshot_locked_mods_changed_user(uint8_t mods) { - if (mods & MOD_MASK_SHIFT) { - println("Oneshot locked mods SHIFT"); - } - if (mods & MOD_MASK_CTRL) { - println("Oneshot locked mods CTRL"); - } - if (mods & MOD_MASK_ALT) { - println("Oneshot locked mods ALT"); - } - if (mods & MOD_MASK_GUI) { - println("Oneshot locked mods GUI"); - } - if (!mods) { - println("Oneshot locked mods off"); - } -} -``` - -Last, there is also a callback for the `OSL(layer)` one shot key: - -```c -void oneshot_layer_changed_user(uint8_t layer) { - if (layer == 1) { - println("Oneshot layer 1 on"); - } - if (!layer) { - println("Oneshot layer off"); - } -} -``` - -If any one shot layer is switched off, `layer` will be zero. When you're looking to do something on any layer change instead of one shot layer changes, `layer_state_set_user` is a better callback to use. - -If you are making your own keyboard, there are also `_kb` equivalent functions: - -```c -void oneshot_locked_mods_changed_kb(uint8_t mods); -void oneshot_mods_changed_kb(uint8_t mods); -void oneshot_layer_changed_kb(uint8_t layer); -``` - -As with any callback, be sure to call the `_user` variant to allow for further customizability. - -# Tap-Hold Configuration Options - -While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonal defaults, but that may still cause issues for some people. - -These options let you modify the behavior of the Tap-Hold keys. - -## Permissive Hold - -As of [PR#1359](https://github.com/qmk/qmk_firmware/pull/1359/), there is a new `config.h` option: - -```c -#define PERMISSIVE_HOLD -``` - -This makes tap and hold keys (like Mod Tap) work better for fast typist, or for high `TAPPING_TERM` settings. - -If you press a Mod Tap key, tap another key (press and release) and then release the Mod Tap key, all within the tapping term, it will output the "tapping" function for both keys. - -For Instance: - -- `SFT_T(KC_A)` Down -- `KC_X` Down -- `KC_X` Up -- `SFT_T(KC_A)` Up - -Normally, if you do all this within the `TAPPING_TERM` (default: 200ms) this will be registered as `ax` by the firmware and host system. With permissive hold enabled, this modifies how this is handled by considering the Mod Tap keys as a Mod if another key is tapped, and would registered as `X` (`SHIFT`+`x`). - -?> If you have `Ignore Mod Tap Interrupt` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`. - -For more granular control of this feature, you can add the following to your `config.h`: - -```c -#define PERMISSIVE_HOLD_PER_KEY -``` - -You can then add the following function to your keymap: - -```c -bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - case SFT_T(KC_A): - return true; - default: - return false; - } -} -``` - -## Ignore Mod Tap Interrupt - -To enable this setting, add this to your `config.h`: - -```c -#define IGNORE_MOD_TAP_INTERRUPT -``` - -Similar to Permissive Hold, this alters how the firmware processes input for fast typist. If you press a Mod Tap key, press another key, release the Mod Tap key, and then release the normal key, it would normally output the "tapping" function for both keys. This may not be desirable for rolling combo keys. - -Setting `Ignore Mod Tap Interrupt` requires holding both keys for the `TAPPING_TERM` to trigger the hold function (the mod). - -For Instance: - -- `SFT_T(KC_A)` Down -- `KC_X` Down -- `SFT_T(KC_A)` Up -- `KC_X` Up - -Normally, this would send `X` (`SHIFT`+`x`). With `Ignore Mod Tap Interrupt` enabled, holding both keys are required for the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold on both will still output `X` (`SHIFT`+`x`). - - -?> __Note__: This only concerns modifiers and not layer switching keys. - -?> If you have `Permissive Hold` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`. - -For more granular control of this feature, you can add the following to your `config.h`: - -```c -#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY -``` - -You can then add the following function to your keymap: - -```c -bool get_ignore_mod_tap_interrupt(uint16_t keycode) { - switch (keycode) { - case SFT_T(KC_SPC): - return true; - default: - return false; - } -} -``` - -## Tapping Force Hold - -To enable `tapping force hold`, add the following to your `config.h`: - -```c -#define TAPPING_FORCE_HOLD -``` - -When the user holds a key after tap, this repeats the tapped key rather to hold a modifier key. This allows to use auto repeat for the tapped key. - -Example: - -- SFT_T(KC_A) Down -- SFT_T(KC_A) Up -- SFT_T(KC_A) Down -- wait more than tapping term... -- SFT_T(KC_A) Up - -With default settings, `a` will be sent on the first release, then `a` will be sent on the second press allowing the computer to trigger its auto repeat function. - -With `TAPPING_FORCE_HOLD`, the second press will be interpreted as a Shift, allowing to use it as a modifier shortly after having used it as a tap. - -!> `TAPPING_FORCE_HOLD` will break anything that uses tapping toggles (Such as the `TT` layer keycode, and the One Shot Tapping Toggle). +# Legacy Content :id=legacy-content -For more granular control of this feature, you can add the following to your `config.h`: +This page used to encompass a large set of features. We have moved many sections that used to be part of this page to their own pages. Everything below this point is simply a redirect so that people following old links on the web find what they're looking for. -```c -#define TAPPING_FORCE_HOLD_PER_KEY -``` +## Layers :id=switching-and-toggling-layers -You can then add the following function to your keymap: +* [Layers](feature_layers.md) -```c -bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - case LT(1, KC_BSPC): - return true; - default: - return false; - } -} -``` +## Mod-Tap :id=mod-tap -## Retro Tapping +* [Mod-Tap](mod_tap.md) -To enable `retro tapping`, add the following to your `config.h`: +## One Shot Keys :id=one-shot-keys -```c -#define RETRO_TAPPING -``` +* [One Shot Keys](one_shot_keys.md) -Holding and releasing a dual function key without pressing another key will result in nothing happening. With retro tapping enabled, releasing the key without pressing another will send the original keycode even if it is outside the tapping term. +## Tap-Hold Configuration Options :id=tap-hold-configuration-options -For instance, holding and releasing `LT(2, KC_SPACE)` without hitting another key will result in nothing happening. With this enabled, it will send `KC_SPACE` instead. +* [Tap-Hold Configuration Options](tap_hold.md) diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md index 7c68d74e1cf9..5f69468c349c 100644 --- a/docs/feature_backlight.md +++ b/docs/feature_backlight.md @@ -192,7 +192,7 @@ To change the behavior of the backlighting, `#define` these in your `config.h`: |`BACKLIGHT_PWM_CHANNEL` |`3` |The PWM channel to use, see ST datasheets for pin to PWM channel mapping. Unless you are designing your own keyboard, you shouldn't need to change this| |`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use, see ST datasheets for pin AF mapping. Unless you are designing your own keyboard, you shouldn't need to change this| -## Software PWM Driver +## Software PWM Driver :id=software-pwm-driver Emulation of PWM while running other keyboard tasks, it offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your rules.mk: ```makefile diff --git a/docs/feature_bootmagic.md b/docs/feature_bootmagic.md index a19b5e548d6e..f084052cc74c 100644 --- a/docs/feature_bootmagic.md +++ b/docs/feature_bootmagic.md @@ -54,7 +54,7 @@ Hold down the Bootmagic key (Space by default) and the desired hotkey while plug |`6` |Make layer 6 the default layer | |`7` |Make layer 7 the default layer | -## Keycodes +## Keycodes :id=keycodes |Key |Aliases |Description | |----------------------------------|---------|--------------------------------------------------------------------------| @@ -121,9 +121,9 @@ If you would like to change the hotkey assignments for Bootmagic, `#define` thes |`BOOTMAGIC_KEY_DEFAULT_LAYER_6` |`KC_6` |Make layer 6 the default layer | |`BOOTMAGIC_KEY_DEFAULT_LAYER_7` |`KC_7` |Make layer 7 the default layer | -# Bootmagic Lite +# Bootmagic Lite :id=bootmagic-lite -In addition to the full blown Bootmagic feature, is the Bootmagic Lite feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button but you need a way to jump into the bootloader, and don't want to deal with the headache that Bootmagic can cause. +In addition to the full blown Bootmagic feature, is the Bootmagic Lite feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button but you need a way to jump into the bootloader, and don't want to deal with the headache that Bootmagic can cause. To enable this version of Bootmagic, you need to enable it in your `rules.mk` with: @@ -131,7 +131,7 @@ To enable this version of Bootmagic, you need to enable it in your `rules.mk` wi BOOTMAGIC_ENABLE = lite ``` -Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file: +Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file: ```c #define BOOTMAGIC_LITE_ROW 0 @@ -144,9 +144,20 @@ And to trigger the bootloader, you hold this key down when plugging the keyboard !> Using bootmagic lite will **always reset** the EEPROM, so you will lose any settings that have been saved. +## Split Keyboards + +When handedness is predetermined via an option like `SPLIT_HAND_PIN`, you might need to configure a different key between halves. This To do so, add these entries to your `config.h` file: + +```c +#define BOOTMAGIC_LITE_ROW_RIGHT 4 +#define BOOTMAGIC_LITE_COLUMN_RIGHT 1 +``` + +By default, these values are not set. + ## Advanced Bootmagic Lite -The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed. +The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed. To replace the function, all you need to do is add something like this to your code: @@ -163,4 +174,4 @@ void bootmagic_lite(void) { } ``` -You can additional feature here. For instance, resetting the eeprom or requiring additional keys to be pressed to trigger bootmagic. Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware. +You can additional feature here. For instance, resetting the eeprom or requiring additional keys to be pressed to trigger bootmagic. Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware. diff --git a/docs/feature_key_lock.md b/docs/feature_key_lock.md index 46935adda067..8e6e29f0e687 100644 --- a/docs/feature_key_lock.md +++ b/docs/feature_key_lock.md @@ -16,7 +16,7 @@ First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Th ## Caveats -Key Lock is only able to hold standard action keys and [One Shot modifier](feature_advanced_keycodes.md#one-shot-keys) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`). +Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`). This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held. Switching layers will not cancel the Key Lock. diff --git a/docs/feature_layers.md b/docs/feature_layers.md new file mode 100644 index 000000000000..c6ffb24053b6 --- /dev/null +++ b/docs/feature_layers.md @@ -0,0 +1,94 @@ +# Layers :id=layers + +One of the most powerful and well used features of QMK Firmware is the ability to use layers. For most people, this amounts to a function key that allows for different keys, much like what you would see on a laptop or tablet keyboard. + +For a detailed explanation of how the layer stack works, checkout [Keymap Overview](keymap.md#keymap-and-layers). + +## Switching and Toggling Layers :id=switching-and-toggling-layers + +These functions allow you to activate layers in various ways. Note that layers are not generally independent layouts -- multiple layers can be activated at once, and it's typical for layers to use `KC_TRNS` to allow keypresses to pass through to lower layers. When using momentary layer switching with MO(), LM(), TT(), or LT(), make sure to leave the key on the above layers transparent or it may not work as intended. + +* `DF(layer)` - switches the default layer. The default layer is the always-active base layer that other layers stack on top of. See below for more about the default layer. This might be used to switch from QWERTY to Dvorak layout. (Note that this is a temporary switch that only persists until the keyboard loses power. To modify the default layer in a persistent way requires deeper customization, such as calling the `set_single_persistent_default_layer` function inside of [process_record_user](custom_quantum_functions.md#programming-the-behavior-of-any-keycode).) +* `MO(layer)` - momentarily activates *layer*. As soon as you let go of the key, the layer is deactivated. +* `LM(layer, mod)` - Momentarily activates *layer* (like `MO`), but with modifier(s) *mod* active. Only supports layers 0-15 and the left modifiers: `MOD_LCTL`, `MOD_LSFT`, `MOD_LALT`, `MOD_LGUI` (note the use of `MOD_` constants instead of `KC_`). These modifiers can be combined using bitwise OR, e.g. `LM(_RAISE, MOD_LCTL | MOD_LALT)`. +* `LT(layer, kc)` - momentarily activates *layer* when held, and sends *kc* when tapped. Only supports layers 0-15. +* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys.md) for details and additional functionality. +* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa +* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed). +* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps. + +### Caveats :id=caveats + +Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Specifically, dual function keys like `LT` and `MT` use a 16 bit keycode. 4 bits are used for the function identifier, the next 12 are divided into the parameters. Layer Tap uses 4 bits for the layer (and is why it's limited to layers 0-16, actually), while Mod Tap does the same, 4 bits for the identifier, 4 bits for which mods are used, and all of them use 8 bits for the keycode. Because of this, the keycode used is limited to `0xFF` (0-255), which are the basic keycodes only. + +Expanding this would be complicated, at best. Moving to a 32-bit keycode would solve a lot of this, but would double the amount of space that the keymap matrix uses. And it could potentially cause issues, too. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this. + +Additionally, if at least one right-handed modifier is specified in a Mod Tap or Layer Tap, it will cause all modifiers specified to become right-handed, so it is not possible to mix and match the two. + +## Working with Layers :id=working-with-layers + +Care must be taken when switching layers, it's possible to lock yourself into a layer with no way to deactivate that layer (without unplugging your keyboard.) We've created some guidelines to help users avoid the most common problems. + +### Beginners :id=beginners + +If you are just getting started with QMK you will want to keep everything simple. Follow these guidelines when setting up your layers: + +* Setup layer 0 as your default, "base" layer. This is your normal typing layer, and could be whatever layout you want (qwerty, dvorak, colemak, etc.). It's important to set this as the lowest layer since it will typically have most or all of the keyboard's keys defined, so would block other layers from having any effect if it were above them (i.e., had a higher layer number). +* Arrange your layers in a "tree" layout, with layer 0 as the root. Do not try to enter the same layer from more than one other layer. +* In a layer's keymap, only reference higher-numbered layers. Because layers are processed from the highest-numbered (topmost) active layer down, modifying the state of lower layers can be tricky and error-prone. + +### Intermediate Users :id=intermediate-users + +Sometimes you need more than one base layer. For example, if you want to switch between QWERTY and Dvorak, switch between layouts for different countries, or switch your layout for different videogames. Your base layers should always be the lowest numbered layers. When you have multiple base layers you should always treat them as mutually exclusive. When one base layer is on the others are off. + +### Advanced Users :id=advanced-users + +Once you have a good feel for how layers work and what you can do, you can get more creative. The rules listed in the beginner section will help you be successful by avoiding some of the tricker details but they can be constraining, especially for ultra-compact keyboard users. Understanding how layers work will allow you to use them in more advanced ways. + +Layers stack on top of each other in numerical order. When determining what a keypress does, QMK scans the layers from the top down, stopping when it reaches the first active layer that is not set to `KC_TRNS`. As a result if you activate a layer that is numerically lower than your current layer, and your current layer (or another layer that is active and higher than your target layer) has something other than `KC_TRNS`, that is the key that will be sent, not the key on the layer you just activated. This is the cause of most people's "why doesn't my layer get switched" problem. + +Sometimes, you might want to switch between layers in a macro or as part of a tap dance routine. `layer_on` activates a layer, and `layer_off` deactivates it. More layer-related functions can be found in [action_layer.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/action_layer.h). + +## Functions :id=functions + +There are a number of functions (and variables) related to how you can use or manipulate the layers. + +|Function |Description | +|----------------------------------------------|---------------------------------------------------------------------------------------------------------| +| `layer_state_set(layer_mask)` | Directly sets the layer state (recommended, do not use unless you know what you are doing). | +| `layer_clear()` | Clears all layers (turns them all off). | +| `layer_move(layer)` | Turns specified layer on, and all other layers off. | +| `layer_on(layer)` | Turns specified layer on, leaves all other layers in existing state. | +| `layer_off(layer)` | Turns specified layer off, leaves all other layers in existing state. | +| `layer_invert(layer)` | Interverts/toggles the state of the specified layer | +| `layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing layer state. | +| `layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing layer state. | +| `layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing layer state. | +| `layer_debug(layer_mask)` | Prints out the current bit mask and highest active layer to debugger console. | +| `default_layer_set(layer_mask)` | Directly sets the default layer state (recommended, do not use unless you know what you are doing). | +| `default_layer_or(layer_mask)` | Turns on layers based on matching bits between specifed layer and existing default layer state. | +| `default_layer_and(layer_mask)` | Turns on layers based on matching enabled bits between specifed layer and existing default layer state. | +| `default_layer_xor(layer_mask)` | Turns on layers based on non-matching bits between specifed layer and existing default layer state. | +| `default_layer_debug(layer_mask)` | Prints out the current bit mask and highest active default layer to debugger console. | +| [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer) | Sets the default layer and writes it to persistent memory (EEPROM). | +| [`update_tri_layer(x, y, z)`](ref_functions.md#update_tri_layerx-y-z) | Checks if layers `x` and `y` are both on, and sets `z` based on that (on if both on, otherwise off). | +| [`update_tri_layer_state(state, x, y, z)`](ref_functions.md#update_tri_layer_statestate-x-y-z) | Does the same as `update_tri_layer(x, y, z)`, but from `layer_state_set_*` functions. | + + +In additional to the functions that you can call, there are a number of callback functions that get called every time the layer changes. This passed the layer state to the function, which can be read or modified. + +|Callbacks |Description | +|-----------------------------------------------------|----------------------------------------------------------------------------------------| +| `layer_state_set_kb(layer_state_t state)` | Callback for layer functions, for keyboard. | +| `layer_state_set_user(layer_state_t state)` | Callback for layer functions, for users. | +| `default_layer_state_set_kb(layer_state_t state)` | Callback for default layer functions, for keyboard. Called on keyboard initialization. | +| `default_layer_state_set_user(layer_state_t state)` | Callback for default layer functions, for users. Called on keyboard initialization. | + +?> For additional details on how you can use these callbacks, check out the [Layer Change Code](custom_quantum_functions.md#layer-change-code) document. + +|Check functions |Description | +|-------------------------------------------|------------------------------------------------------------------------------| +| `layer_state_cmp(cmp_layer_state, layer)` | This checks the `cmp_layer_state` to see if the specific `layer` is enabled. This is meant for use with the layer callbacks. | +| `layer_state_is(layer)` | This checks the layer state to see if the specific `layer` is enabled. (calls `layer_state_cmp` for the global layer state). | + +!> There is `IS_LAYER_ON(layer)` as well, however the `layer_state_cmp` function has some additional handling to ensure that on layer 0 that it returns the correct value. Otherwise, if you check to see if layer 0 is on, you may get an incorrect value returned. diff --git a/docs/feature_leader_key.md b/docs/feature_leader_key.md index 22370bf230ef..828d6557d3e6 100644 --- a/docs/feature_leader_key.md +++ b/docs/feature_leader_key.md @@ -74,9 +74,9 @@ SEQ_THREE_KEYS(KC_C, KC_C, KC_C) { ## Strict Key Processing -By default, the Leader Key feature will filter the keycode out of [`Mod-Tap`](feature_advanced_keycodes.md#mod-tap) and [`Layer Tap`](feature_advanced_keycodes.md#switching-and-toggling-layers) functions when checking for the Leader sequences. That means if you're using `LT(3, KC_A)`, it will pick this up as `KC_A` for the sequence, rather than `LT(3, KC_A)`, giving a more expected behavior for newer users. +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 added `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This well then disable the filtering, and you'll need to specify the whole keycode. +While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by added `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This will then disable the filtering, and you'll need to specify the whole keycode. ## Customization diff --git a/docs/feature_macros.md b/docs/feature_macros.md index 99dd564bf8ae..1bd2d74e7d99 100644 --- a/docs/feature_macros.md +++ b/docs/feature_macros.md @@ -88,6 +88,46 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; ``` +### Advanced Macros + +In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance. + +In this example, we modify most normal keypresses so that `F22` is pressed before the keystroke is normally sent, and release it __only after__ it's been released. + +```c +static uint8_t f22_tracker; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case KC_A ... KC_F21: //notice how it skips over F22 + case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys + if (record->event.pressed) { + register_code(KC_F22); //this means to send F22 down + f22_tracker++; + register_code(keycode); + return false; + } + break; + } + return true; +} + +void post_process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case KC_A ... KC_F21: //notice how it skips over F22 + case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys + if (!record->event.pressed) { + f22_tracker--; + if (!f22_tracker) { + unregister_code(KC_F22); //this means to send F22 up + } + } + break; + } +} +``` + + ### TAP, DOWN and UP You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`. diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md index 363662f633b7..88a2c7c05e54 100644 --- a/docs/feature_mouse_keys.md +++ b/docs/feature_mouse_keys.md @@ -58,6 +58,8 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u |`MOUSEKEY_INTERVAL` |50 |Time between cursor movements | |`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops | |`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached | +|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement | +|`MOUSEKEY_WHEEL_INTERVAL` |100 |Time between wheel movements | |`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action | |`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached | @@ -66,6 +68,7 @@ Tips: * Setting `MOUSEKEY_DELAY` too low makes the cursor unresponsive. Setting it too high makes small movements difficult. * For smoother cursor movements, lower the value of `MOUSEKEY_INTERVAL`. If the refresh rate of your display is 60Hz, you could set it to `16` (1/60). As this raises the cursor speed significantly, you may want to lower `MOUSEKEY_MAX_SPEED`. * Setting `MOUSEKEY_TIME_TO_MAX` or `MOUSEKEY_WHEEL_TIME_TO_MAX` to `0` will disable acceleration for the cursor or scrolling respectively. This way you can make one of them constant while keeping the other accelerated, which is not possible in constant speed mode. +* Setting `MOUSEKEY_WHEEL_INTERVAL` too low will make scrolling too fast. Setting it too high will make scrolling too slow when the wheel key is held down. Cursor acceleration uses the same algorithm as the X Window System MouseKeysAccel feature. You can read more about it [on Wikipedia](https://en.wikipedia.org/wiki/Mouse_keys). diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md index ebabc314ffec..772ce57bdd29 100644 --- a/docs/feature_oled_driver.md +++ b/docs/feature_oled_driver.md @@ -221,6 +221,12 @@ void oled_write(const char *data, bool invert); // Advances the cursor to the next page, wiring ' ' to the remainder of the current page void oled_write_ln(const char *data, bool invert); +// Pans the buffer to the right (or left by passing true) by moving contents of the buffer +// Useful for moving the screen in preparation for new drawing +// oled_scroll_left or oled_scroll_right should be preferred for all cases of moving a static +// image such as a logo or to avoid burn-in as it's much, much less cpu intensive +void oled_pan(bool left); + // Writes a PROGMEM string to the buffer at current cursor position // Advances the cursor while writing, inverts the pixels if true // Remapped to call 'void oled_write(const char *data, bool invert);' on ARM @@ -235,6 +241,9 @@ void oled_write_ln_P(const char *data, bool invert); // Writes a string to the buffer at current cursor position void oled_write_raw(const char *data, uint16_t size); +// Writes a single byte into the buffer at the specified index +void oled_write_raw_byte(const char data, uint16_t index); + // Writes a PROGMEM string to the buffer at current cursor position void oled_write_raw_P(const char *data, uint16_t size); @@ -252,12 +261,24 @@ void oled_task(void); // Called at the start of oled_task, weak function overridable by the user void oled_task_user(void); -// Scrolls the entire display right +// Set the specific 8 lines rows of the screen to scroll. +// 0 is the default for start, and 7 for end, which is the entire +// height of the screen. For 128x32 screens, rows 4-7 are not used. +void oled_scroll_set_area(uint8_t start_line, uint8_t end_line); + +// Sets scroll speed, 0-7, fastest to slowest. Default is three. +// Does not take effect until scrolling is either started or restarted +// the ssd1306 supports 8 speeds with the delay +// listed below betwen each frame of the scrolling effect +// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256 +void oled_scroll_set_speed(uint8_t speed); + +// Begin scrolling the entire display right // Returns true if the screen was scrolling or starts scrolling // NOTE: display contents cannot be changed while scrolling bool oled_scroll_right(void); -// Scrolls the entire display left +// Begin scrolling the entire display left // Returns true if the screen was scrolling or starts scrolling // NOTE: display contents cannot be changed while scrolling bool oled_scroll_left(void); diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md index 8ad428939a0a..b90c341d5ed7 100644 --- a/docs/feature_pointing_device.md +++ b/docs/feature_pointing_device.md @@ -1,10 +1,10 @@ -## Pointing Device +# Pointing Device :id=pointing-device Pointing Device is a generic name for a feature intended to be generic: moving the system pointer around. There are certainly other options for it - like mousekeys - but this aims to be easily modifiable and lightweight. You can implement custom keys to control functionality, or you can gather information from other peripherals and insert it directly here - let QMK handle the processing for you. To enable Pointing Device, uncomment the following line in your rules.mk: -``` +```makefile POINTING_DEVICE_ENABLE = yes ``` @@ -25,7 +25,7 @@ When the mouse report is sent, the x, y, v, and h values are set to 0 (this is d In the following example, a custom key is used to click the mouse and scroll 127 units vertically and horizontally, then undo all of that when released - because that's a totally useful function. Listen, this is an example: -``` +```c case MS_SPECIAL: report_mouse_t currentReport = pointing_device_get_report(); if (record->event.pressed) diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md index d138967991fe..ce072fbe935e 100644 --- a/docs/feature_ps2_mouse.md +++ b/docs/feature_ps2_mouse.md @@ -1,4 +1,4 @@ -## PS/2 Mouse Support +# PS/2 Mouse Support :id=ps2-mouse-support Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device. @@ -6,7 +6,7 @@ To hook up a Trackpoint, you need to obtain a Trackpoint module (i.e. harvest fr There are three available modes for hooking up PS/2 devices: USART (best), interrupts (better) or busywait (not recommended). -### The Cirtuitry between Trackpoint and Controller +## The Circuitry between Trackpoint and Controller :id=the-circuitry-between-trackpoint-and-controller To get the things working, a 4.7K drag is needed between the two lines DATA and CLK and the line 5+. @@ -24,20 +24,20 @@ MODULE 5+ --------+--+--------- PWR CONTROLLER ``` -### Busywait Version +## Busywait Version :id=busywait-version Note: This is not recommended, you may encounter jerky movement or unsent inputs. Please use interrupt or USART version if possible. In rules.mk: -``` +```makefile PS2_MOUSE_ENABLE = yes PS2_USE_BUSYWAIT = yes ``` In your keyboard config.h: -``` +```c #ifdef PS2_USE_BUSYWAIT # define PS2_CLOCK_PORT PORTD # define PS2_CLOCK_PIN PIND @@ -50,20 +50,20 @@ In your keyboard config.h: #endif ``` -### Interrupt Version +## Interrupt Version :id=interrupt-version The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data. In rules.mk: -``` +```makefile PS2_MOUSE_ENABLE = yes PS2_USE_INT = yes ``` In your keyboard config.h: -``` +```c #ifdef PS2_USE_INT #define PS2_CLOCK_PORT PORTD #define PS2_CLOCK_PIN PIND @@ -88,20 +88,20 @@ In your keyboard config.h: #endif ``` -### USART Version +## USART Version :id=usart-version To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version. In rules.mk: -``` +```makefile PS2_MOUSE_ENABLE = yes PS2_USE_USART = yes ``` In your keyboard config.h: -``` +```c #ifdef PS2_USE_USART #define PS2_CLOCK_PORT PORTD #define PS2_CLOCK_PIN PIND @@ -145,13 +145,13 @@ In your keyboard config.h: #endif ``` -### Additional Settings +## Additional Settings :id=additional-settings -#### PS/2 Mouse Features +### PS/2 Mouse Features :id=ps2-mouse-features These enable settings supported by the PS/2 mouse protocol. -``` +```c /* Use remote mode instead of the default stream mode (see link) */ #define PS2_MOUSE_USE_REMOTE_MODE @@ -170,7 +170,7 @@ These enable settings supported by the PS/2 mouse protocol. You can also call the following functions from ps2_mouse.h -``` +```c void ps2_mouse_disable_data_reporting(void); void ps2_mouse_enable_data_reporting(void); @@ -188,36 +188,36 @@ void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution); void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate); ``` -#### Fine Control +### Fine Control :id=fine-control Use the following defines to change the sensitivity and speed of the mouse. Note: you can also use `ps2_mouse_set_resolution` for the same effect (not supported on most touchpads). -``` +```c #define PS2_MOUSE_X_MULTIPLIER 3 #define PS2_MOUSE_Y_MULTIPLIER 3 #define PS2_MOUSE_V_MULTIPLIER 1 ``` -#### Scroll Button +### Scroll Button :id=scroll-button If you're using a trackpoint, you will likely want to be able to use it for scrolling. It's possible to enable a "scroll button/s" that when pressed will cause the mouse to scroll instead of moving. To enable the feature, you must set a scroll button mask as follows: -``` +```c #define PS2_MOUSE_SCROLL_BTN_MASK (1<.c`: -```C +```c const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver @@ -55,19 +55,19 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/issi/is31fl3731.h`. The `driver` is the index of the driver you defined in your `config.h` (`0` or `1` right now). --- -### IS31FL3733/IS31FL3737 +### IS31FL3733/IS31FL3737 :id=is31fl3733is31fl3737 !> For the IS31FL3737, replace all instances of `IS31FL3733` below with `IS31FL3737`. There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`: -```C +```makefile RGB_MATRIX_ENABLE = IS31FL3733 ``` Configure the hardware via your `config.h`: -```C +```c // This is a 7-bit address, that gets left-shifted and bit 0 // set to 0 for write, 1 for read (as per I2C protocol) // The address will vary depending on your wiring: @@ -90,7 +90,7 @@ Currently only a single drivers is supported, but it would be trivial to support Define these arrays listing all the LEDs in your `.c`: -```C +```c const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver @@ -107,17 +107,17 @@ Where `X_Y` is the location of the LED in the matrix defined by [the datasheet]( --- -### WS2812 +### WS2812 :id=ws2812 There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{a,b,c} addressable LED strand. To enable it, add this to your `rules.mk`: -```C +```makefile RGB_MATRIX_ENABLE = WS2812 ``` Configure the hardware via your `config.h`: -```C +```c // The pin connected to the data pin of the LEDs #define RGB_DI_PIN D7 // The number of LEDs connected @@ -128,7 +128,7 @@ Configure the hardware via your `config.h`: From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example: -```C +```c const led_config_t g_led_config = { { // Key Matrix to LED Index { 5, NO_LED, NO_LED, 0 }, @@ -146,7 +146,7 @@ const led_config_t g_led_config = { { The first part, `// Key Matrix to LED Index`, tells the system what key this LED represents by using the key's electrical matrix row & col. The second part, `// LED Index to Physical Position` represents the LED's physical `{ x, y }` position on the keyboard. The default expected range of values for `{ x, y }` is the inclusive range `{ 0..224, 0..64 }`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position: -```C +```c x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION ``` @@ -157,7 +157,7 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{ `// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type. -## Flags +## Flags :id=flags |Define |Description | |------------------------------------|-------------------------------------------| @@ -169,7 +169,7 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{ |`#define LED_FLAG_UNDERGLOW 0x02` |If the LED is for underglow. | |`#define LED_FLAG_KEYLIGHT 0x04` |If the LED is for key backlight. | -## Keycodes +## Keycodes :id=keycodes All RGB keycodes are currently shared with the RGBLIGHT system: @@ -189,11 +189,11 @@ All RGB keycodes are currently shared with the RGBLIGHT system: * `RGB_MODE_*` keycodes will generally work, but are not currently mapped to the correct effects for the RGB Matrix system -## RGB Matrix Effects +## RGB Matrix Effects :id=rgb-matrix-effects All effects have been configured to support current configuration values (Hue, Saturation, Value, & Speed) unless otherwise noted below. These are the effects that are currently available: -```C +```c enum rgb_matrix_effects { RGB_MATRIX_NONE = 0, RGB_MATRIX_SOLID_COLOR = 1, // Static single hue, no speed support @@ -285,7 +285,7 @@ You can disable a single effect by defining `DISABLE_[EFFECT_NAME]` in your `con |`#define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Disables `RGB_MATRIX_SOLID_MULTISPLASH` | -## Custom RGB Matrix Effects +## Custom RGB Matrix Effects :id=custom-rgb-matrix-effects By setting `RGB_MATRIX_CUSTOM_USER` (and/or `RGB_MATRIX_CUSTOM_KB`) in `rules.mk`, new effects can be defined directly from userspace, without having to edit any QMK core files. @@ -294,7 +294,7 @@ To declare new effects, create a new `rgb_matrix_user/kb.inc` that looks somethi `rgb_matrix_user.inc` should go in the root of the keymap directory. `rgb_matrix_kb.inc` should go in the root of the keyboard directory. -```C +```c // !!! DO NOT ADD #pragma once !!! // // Step 1. @@ -341,7 +341,7 @@ static bool my_cool_effect2(effect_params_t* params) { For inspiration and examples, check out the built-in effects under `quantum/rgb_matrix_animation/` -## Colors +## Colors :id=colors These are shorthands to popular colors. The `RGB` ones can be passed to the `setrgb` functions, while the `HSV` ones to the `sethsv` functions. @@ -369,9 +369,9 @@ These are shorthands to popular colors. The `RGB` ones can be passed to the `set These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h). Feel free to add to this list! -## Additional `config.h` Options +## Additional `config.h` Options :id=additional-configh-options -```C +```c #define RGB_MATRIX_KEYPRESSES // reacts to keypresses #define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects @@ -386,28 +386,98 @@ These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blo #define RGB_MATRIX_STARTUP_SPD 127 // Sets the default animation speed, if none has been set ``` -## EEPROM storage +## EEPROM storage :id=eeprom-storage The EEPROM for it is currently shared with the RGBLIGHT system (it's generally assumed only one RGB would be used at a time), but could be configured to use its own 32bit address with: -```C +```c #define EECONFIG_RGB_MATRIX (uint32_t *)28 ``` Where `28` is an unused index from `eeconfig.h`. -## Suspended state +## Functions :id=functions + +### Direct Operation :id=direct-operation +|Function |Description | +|--------------------------------------------|-------------| +|`rgb_matrix_set_color_all(r, g, b)` |Set all of the LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) | +|`rgb_matrix_set_color(index, r, g, b)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255, and `index` is between 0 and `DRIVER_LED_TOTAL` (not written to EEPROM) | + +### Disable/Enable Effects :id=disable-enable-effects +|Function |Description | +|--------------------------------------------|-------------| +|`rgb_matrix_toggle()` |Toggle effect range LEDs between on and off | +|`rgb_matrix_toggle_noeeprom()` |Toggle effect range LEDs between on and off (not written to EEPROM) | +|`rgb_matrix_enable()` |Turn effect range LEDs on, based on their previous state | +|`rgb_matrix_enable_noeeprom()` |Turn effect range LEDs on, based on their previous state (not written to EEPROM) | +|`rgb_matrix_disable()` |Turn effect range LEDs off | +|`rgb_matrix_disable_noeeprom()` |Turn effect range LEDs off (not written to EEPROM) | + +### Change Effect Mode :id=change-effect-mode +|Function |Description | +|--------------------------------------------|-------------| +|`rgb_matrix_mode(mode)` |Set the mode, if RGB animations are enabled | +|`rgb_matrix_mode_noeeprom(mode)` |Set the mode, if RGB animations are enabled (not written to EEPROM) | +|`rgb_matrix_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations | +|`rgb_matrix_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations | +|`rgb_matrix_increase_speed()` |Increases the speed of the animations | +|`rgb_matrix_decrease_speed()` |Decreases the speed of the animations | + +### Change Color :id=change-color +|Function |Description | +|--------------------------------------------|-------------| +|`rgb_matrix_increase_hue()` |Increase the hue for effect range LEDs. This wraps around at maximum hue | +|`rgb_matrix_decrease_hue()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue | +|`rgb_matrix_increase_sat()` |Increase the saturation for effect range LEDs. This wraps around at maximum saturation | +|`rgb_matrix_decrease_sat()` |Decrease the saturation for effect range LEDs. This wraps around at minimum saturation | +|`rgb_matrix_increase_val()` |Increase the value for effect range LEDs. This wraps around at maximum value | +|`rgb_matrix_decrease_val()` |Decrease the value for effect range LEDs. This wraps around at minimum value | +|`rgb_matrix_sethsv(h, s, v)` |Set LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 | +|`rgb_matrix_sethsv_noeeprom(h, s, v)` |Set LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) | + +### Query Current Status :id=query-current-status +|Function |Description | +|-----------------------|-----------------| +|`rgb_matrix_get_mode()` |Get current mode | +|`rgb_matrix_get_hue()` |Get current hue | +|`rgb_matrix_get_sat()` |Get current sat | +|`rgb_matrix_get_val()` |Get current val | + +## Callbacks :id=callbacks + +### Indicators :id=indicators + +If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `rgb_matrix_indicators_kb` or `rgb_matrix_indicators_user` function for that: +```c +void rgb_matrix_indicators_kb(void) { + rgb_matrix_set_color(index, red, green, blue); +} +``` + +### Suspended state :id=suspended-state +To use the suspend feature, make sure that `#define RGB_DISABLE_WHEN_USB_SUSPENDED true` is added to the `config.h` file. -To use the suspend feature, add this to your `.c`: +Additionally add this to your `.c`: -```C -void suspend_power_down_kb(void) -{ +```c +void suspend_power_down_kb(void) { + rgb_matrix_set_suspend_state(true); + suspend_power_down_user(); +} + +void suspend_wakeup_init_kb(void) { + rgb_matrix_set_suspend_state(false); + suspend_wakeup_init_user(); +} +``` +or add this to your `keymap.c`: +```c +void suspend_power_down_user(void) { rgb_matrix_set_suspend_state(true); } -void suspend_wakeup_init_kb(void) -{ +void suspend_wakeup_init_user(void) { rgb_matrix_set_suspend_state(false); } ``` diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md index 69a6aaaed6b7..219cd8317b7c 100644 --- a/docs/feature_rgblight.md +++ b/docs/feature_rgblight.md @@ -172,6 +172,64 @@ const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31}; const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64}; ``` +## Lighting Layers + +By including `#define RGBLIGHT_LAYERS` in your `config.h` file you can enable lighting layers. These make +it easy to use your underglow LEDs as status indicators to show which keyboard layer is currently active, or the state of caps lock, all without disrupting any animations. [Here's a video](https://youtu.be/uLGE1epbmdY) showing an example of what you can do. + +To define a layer, we modify `keymap.c` to list out LED ranges and the colors we want to overlay on them using an array of `rgblight_segment_t` using the `RGBLIGHT_LAYER_SEGMENTS` macro. We can define multiple layers and enable/disable them independently: + +```c +// Light LEDs 6 to 9 and 12 to 15 red when caps lock is active. Hard to ignore! +const rgblight_segment_t PROGMEM my_capslock_layer[] = RGBLIGHT_LAYER_SEGMENTS( + {6, 4, HSV_RED}, // Light 4 LEDs, starting with LED 6 + {12, 4, HSV_RED} // Light 4 LEDs, starting with LED 12 +); +// Light LEDs 9 & 10 in cyan when keyboard layer 1 is active +const rgblight_segment_t PROGMEM my_layer1_layer[] = RGBLIGHT_LAYER_SEGMENTS( + {9, 2, HSV_CYAN} +); +// Light LEDs 11 & 12 in purple when keyboard layer 2 is active +const rgblight_segment_t PROGMEM my_layer2_layer[] = RGBLIGHT_LAYER_SEGMENTS( + {11, 2, HSV_PURPLE} +); +// etc.. +``` + +We combine these layers into an array using the `RGBLIGHT_LAYERS_LIST` macro, and assign it to the `rgblight_layers` variable during keyboard setup. Note that you can only define up to 8 lighting layers. Any extra layers will be ignored. Since the different lighting layers overlap, the order matters in the array, with later layers taking precedence: + +```c +// Now define the array of layers. Later layers take precedence +const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST( + my_capslock_layer, + my_layer1_layer, // Overrides caps lock layer + my_layer2_layer // Overrides other layers +); + +void keyboard_post_init_user(void) { + // Enable the LED layers + rgblight_layers = my_rgb_layers; +} +``` + +Finally, we enable and disable the lighting layers whenever the state of the keyboard changes: + +```c +layer_state_t layer_state_set_user(layer_state_t state) { + // Both layers will light up if both kb layers are active + rgblight_set_layer_state(1, layer_state_cmp(state, 1)); + rgblight_set_layer_state(2, layer_state_cmp(state, 2)); + return state; +} + +bool led_update_user(led_t led_state) { + rgblight_set_layer_state(0, led_state.caps_lock); + return true; +} +``` + +Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers. + ## Functions If you need to change your RGB lighting in code, for example in a macro to change the color whenever you switch layers, QMK provides a set of functions to assist you. See [`rgblight.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h) for the full list, but the most commonly used functions include: @@ -263,6 +321,12 @@ rgblight_sethsv(HSV_GREEN, 2); // led 2 |`rgblight_sethsv(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 | |`rgblight_sethsv_noeeprom(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) | +#### layer functions +|Function |Description | +|--------------------------------------------|-------------| +|`rgblight_get_layer_state(i)` |Returns `true` if lighting layer `i` is enabled | +|`rgblight_set_layer_state(i, is_on)` |Enable or disable lighting layer `i` based on value of `bool is_on` | + #### query |Function |Description | |-----------------------|-----------------| diff --git a/docs/feature_stenography.md b/docs/feature_stenography.md index 0b2c82422b66..099993f85799 100644 --- a/docs/feature_stenography.md +++ b/docs/feature_stenography.md @@ -1,16 +1,16 @@ -# Stenography in QMK +# Stenography in QMK :id=stenography-in-qmk [Stenography](https://en.wikipedia.org/wiki/Stenotype) is a method of writing most often used by court reports, closed-captioning, and real-time transcription for the deaf. In stenography words are chorded syllable by syllable with a mixture of spelling, phonetic, and shortcut (briefs) strokes. Professional stenographers can reach 200-300 WPM without any of the strain usually found in standard typing and with far fewer errors (>99.9% accuracy). The [Open Steno Project](http://www.openstenoproject.org/) has built an open-source program called Plover that provides real-time translation of steno strokes into words and commands. It has an established dictionary and supports -## Plover with QWERTY Keyboard +## Plover with QWERTY Keyboard :id=plover-with-qwerty-keyboard Plover can work with any standard QWERTY keyboard, although it is more efficient if the keyboard supports NKRO (n-key rollover) to allow Plover to see all the pressed keys at once. An example keymap for Plover can be found in `planck/keymaps/default`. Switching to the `PLOVER` layer adjusts the position of the keyboard to support the number bar. To use Plover with QMK just enable NKRO and optionally adjust your layout if you have anything other than a standard layout. You may also want to purchase some steno-friendly keycaps to make it easier to hit multiple keys. -## Plover with Steno Protocol +## Plover with Steno Protocol :id=plover-with-steno-protocol Plover also understands the language of several steno machines. QMK can speak a couple of these languages, TX Bolt and GeminiPR. An example layout can be found in `planck/keymaps/steno`. @@ -20,26 +20,26 @@ In this mode Plover expects to speak with a steno machine over a serial port so > Note: Due to hardware limitations you may not be able to run both a virtual serial port and mouse emulation at the same time. -### TX Bolt +### TX Bolt :id=tx-bolt TX Bolt communicates the status of 24 keys over a very simple protocol in variable-sized (1-5 byte) packets. -### GeminiPR +### GeminiPR :id=geminipr GeminiPR encodes 42 keys into a 6-byte packet. While TX Bolt contains everything that is necessary for standard stenography, GeminiPR opens up many more options, including supporting non-English theories. -## Configuring QMK for Steno +## Configuring QMK for Steno :id=configuring-qmk-for-steno Firstly, enable steno in your keymap's Makefile. You may also need disable mousekeys, extra keys, or another USB endpoint to prevent conflicts. The builtin USB stack for some processors only supports a certain number of USB endpoints and the virtual serial port needed for steno fills 3 of them. -```Makefile +```makefile STENO_ENABLE = yes MOUSEKEY_ENABLE = no ``` In your keymap create a new layer for Plover. You will need to include `keymap_steno.h`. See `planck/keymaps/steno/keymap.c` for an example. Remember to create a key to switch to the layer as well as a key for exiting the layer. If you would like to switch modes on the fly you can use the keycodes `QK_STENO_BOLT` and `QK_STENO_GEMINI`. If you only want to use one of the protocols you may set it up in your initialization function: -```C +```c void matrix_init_user() { steno_set_mode(STENO_MODE_GEMINI); // or STENO_MODE_BOLT } @@ -49,37 +49,37 @@ Once you have your keyboard flashed launch Plover. Click the 'Configure...' butt On the display tab click 'Open stroke display'. With Plover disabled you should be able to hit keys on your keyboard and see them show up in the stroke display window. Use this to make sure you have set up your keymap correctly. You are now ready to steno! -## Learning Stenography +## Learning Stenography :id=learning-stenography -* [Learn Plover!](https://sites.google.com/site/ploverdoc/) +* [Learn Plover!](https://sites.google.com/site/learnplover/) * [QWERTY Steno](http://qwertysteno.com/Home/) * [Steno Jig](https://joshuagrams.github.io/steno-jig/) * More resources at the Plover [Learning Stenography](https://github.com/openstenoproject/plover/wiki/Learning-Stenography) wiki -## Interfacing with the code +## Interfacing with the code :id=interfacing-with-the-code The steno code has three interceptible hooks. If you define these functions, they will be called at certain points in processing; if they return true, processing continues, otherwise it's assumed you handled things. -```C +```c bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]); ``` This function is called when a chord is about to be sent. Mode will be one of `STENO_MODE_BOLT` or `STENO_MODE_GEMINI`. This represents the actual chord that would be sent via whichever protocol. You can modify the chord provided to alter what gets sent. Remember to return true if you want the regular sending process to happen. -```C +```c bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; } ``` This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_BOLT`, `QK_STENO_GEMINI`, or one of the `STN_*` key values. -```C +```c bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed); ``` This function is called after a key has been processed, but before any decision about whether or not to send a chord. If `IS_PRESSED(record->event)` is false, and `pressed` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This is where to put hooks for things like, say, live displays of steno chords or keys. -## Keycode Reference +## Keycode Reference :id=keycode-reference As defined in `keymap_steno.h`. diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md index f48f11b1cb1a..2e8ab5350663 100644 --- a/docs/feature_tap_dance.md +++ b/docs/feature_tap_dance.md @@ -335,7 +335,7 @@ If you want to implement this in your userspace, then you may want to check out > In this configuration "hold" takes place **after** tap dance timeout (see `ACTION_TAP_DANCE_FN_ADVANCED_TIME`). To achieve instant hold, remove `state->interrupted` checks in conditions. As a result you may use comfortable longer tapping periods to have more time for taps and not to wait too long for holds (try starting with doubled `TAPPING_TERM`). -### Example 5: Using tap dance for advanced mod-tap and layer-tap keys +### Example 5: Using tap dance for advanced mod-tap and layer-tap keys :id=example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`. diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md index 697541458809..a6f2cb4d0de9 100644 --- a/docs/feature_unicode.md +++ b/docs/feature_unicode.md @@ -90,13 +90,15 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort The following input modes are available: -* **`UC_OSX`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map). +* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map). To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar. - By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_OSX`](#input-key-configuration) with another keycode. + By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with another keycode. !> Using the _Unicode Hex Input_ input source may disable some Option based shortcuts, such as Option + Left Arrow and Option + Right Arrow. + !> `UC_OSX` is a deprecated alias of `UC_MAC` that will be removed in a future version of QMK. + * **`UC_LNX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points). Enabled by default and works almost anywhere on IBus-enabled distros. Without IBus, this mode works under GTK apps, but rarely anywhere else. @@ -124,7 +126,7 @@ You can switch the input mode at any time by using one of the following keycodes |----------------------|---------|------------|--------------------------------------------------------------| |`UNICODE_MODE_FORWARD`|`UC_MOD` |Next in list|[Cycle](#input-mode-cycling) through selected modes | |`UNICODE_MODE_REVERSE`|`UC_RMOD`|Prev in list|[Cycle](#input-mode-cycling) through selected modes in reverse| -|`UNICODE_MODE_OSX` |`UC_M_OS`|`UC_OSX` |Switch to macOS input | +|`UNICODE_MODE_MAC` |`UC_M_MA`|`UC_MAC` |Switch to macOS input | |`UNICODE_MODE_LNX` |`UC_M_LN`|`UC_LNX` |Switch to Linux input | |`UNICODE_MODE_WIN` |`UC_M_WI`|`UC_WIN` |Switch to Windows input | |`UNICODE_MODE_BSD` |`UC_M_BS`|`UC_BSD` |Switch to BSD input (not implemented) | @@ -145,9 +147,9 @@ If you have the [Audio feature](feature_audio.md) enabled on the board, you can For instance, you can add these definitions to your `config.h` file: ```c -#define UNICODE_SONG_OSX COIN_SOUND +#define UNICODE_SONG_MAC AUDIO_ON_SOUND #define UNICODE_SONG_LNX UNICODE_LINUX -#define UNICODE_SONG_BSD MARIO_GAMEOVER +#define UNICODE_SONG_BSD TERMINAL_SOUND #define UNICODE_SONG_WIN UNICODE_WINDOWS #define UNICODE_SONG_WINC UNICODE_WINDOWS ``` @@ -171,7 +173,7 @@ You can customize the keys used to trigger Unicode input for macOS, Linux and Wi |Define |Type |Default |Example | |------------------|----------|------------------|-------------------------------------------| -|`UNICODE_KEY_OSX` |`uint8_t` |`KC_LALT` |`#define UNICODE_KEY_OSX KC_RALT` | +|`UNICODE_KEY_MAC` |`uint8_t` |`KC_LALT` |`#define UNICODE_KEY_MAC KC_RALT` | |`UNICODE_KEY_LNX` |`uint16_t`|`LCTL(LSFT(KC_U))`|`#define UNICODE_KEY_LNX LCTL(LSFT(KC_E))`| |`UNICODE_KEY_WINC`|`uint8_t` |`KC_RALT` |`#define UNICODE_KEY_WINC KC_RGUI` | @@ -180,7 +182,7 @@ You can customize the keys used to trigger Unicode input for macOS, Linux and Wi You can choose which input modes are available for cycling through. By default, this is disabled. If you want to enable it, limiting it to just the modes you use makes sense. Note that the values in the list are comma-delimited. ```c -#define UNICODE_SELECTED_MODES UC_OSX, UC_LNX, UC_WIN, UC_WINC +#define UNICODE_SELECTED_MODES UC_MAC, UC_LNX, UC_WIN, UC_WINC ``` You can cycle through the selected modes by using the `UC_MOD`/`UC_RMOD` keycodes, or by calling `cycle_unicode_input_mode(offset)` in your code (`offset` is how many modes to move forward by, so +1 corresponds to `UC_MOD`). diff --git a/docs/feature_userspace.md b/docs/feature_userspace.md index a2657c1f6065..ac0a1360d92d 100644 --- a/docs/feature_userspace.md +++ b/docs/feature_userspace.md @@ -97,13 +97,25 @@ You'd want to replace the year, name, email and github username with your info. Additionally, this is a good place to document your code, if you wish to share it with others. -# Examples +## Build All Keyboards That Support a Specific Keymap + +Want to check all your keymaps build in a single command? You can run: + + make all: + +For example, + + make all:jack + +This is ideal for when you want ensure everything compiles successfully when preparing a [_Pull request_](https://github.com/qmk/qmk_firmware/pulls). + +## Examples For a brief example, checkout [`/users/_example/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna). For a more complicated example, checkout [`/users/drashna/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna)'s userspace. -## Customized Functions +### Customized Functions QMK has a bunch of [functions](custom_quantum_functions.md) that have [`_quantum`, `_kb`, and `_user` versions](custom_quantum_functions.md#a-word-on-core-vs-keyboards-vs-keymap) that you can use. You will pretty much always want to use the user version of these functions. But the problem is that if you use them in your userspace, then you don't have a version that you can use in your keymap. @@ -130,7 +142,7 @@ The `_keymap` part here doesn't matter, it just needs to be something other than You can see a list of this and other common functions in [`template.c`](https://github.com/qmk/qmk_firmware/blob/master/users/drashna/template.c) in [`users/drashna`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna). -## Custom Features +### Custom Features Since the Userspace feature can support a staggering number of boards, you may have boards that you want to enable certain functionality for, but not for others. And you can actually create "features" that you can enable or disable in your own userspace. @@ -166,7 +178,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { ``` -## Consolidated Macros +### Consolidated Macros If you wanted to consolidate macros and other functions into your userspace for all of your keymaps, you can do that. This builds upon the [Customized Functions](#customized-functions) example above. This lets you maintain a bunch of macros that are shared between the different keyboards, and allow for keyboard specific macros, too. diff --git a/docs/feature_wpm.md b/docs/feature_wpm.md new file mode 100644 index 000000000000..12dd08057985 --- /dev/null +++ b/docs/feature_wpm.md @@ -0,0 +1,25 @@ +# Word Per Minute (WPM) Calculcation + +The WPM feature uses time between keystrokes to compute a rolling average words +per minute rate and makes this available for various uses. + +Enable the WPM system by adding this to your `rules.mk`: + + WPM_ENABLE = yes + +For split keyboards using soft serial, the computed WPM +score will be available on the master AND slave half. + +## Public Functions + +`uint8_t get_current_wpm(void);` +This function returns the current WPM as an unsigned integer. + + +## Customized keys for WPM calc + +By default, the WPM score only includes letters, numbers, space and some +punctuation. If you want to change the set of characters considered as part of +the WPM calculation, you can implement `wpm_keycode_user(uint16_t keycode)` +and return true for any characters you would like included in the calculation, +or false to not count that particular keycode. diff --git a/docs/features.md b/docs/features.md deleted file mode 100644 index 44299bf10dcb..000000000000 --- a/docs/features.md +++ /dev/null @@ -1,42 +0,0 @@ -# QMK Features - -QMK has a staggering number of features for building your keyboard. It can take some time to understand all of them and determine which one will achieve your goal. - - -* [Advanced Keycodes](feature_advanced_keycodes.md) - Change layers, dual-action keys, and more. Go beyond typing simple characters. -* [Audio](feature_audio.md) - Connect a speaker to your keyboard for audio feedback, midi support, and music mode. -* [Auto Shift](feature_auto_shift.md) - Tap for the normal key, hold slightly longer for its shifted state. -* [Backlight](feature_backlight.md) - LED lighting support for your keyboard. -* [Bluetooth](feature_bluetooth.md) - BlueTooth support for your keyboard. -* [Bootmagic](feature_bootmagic.md) - Adjust the behavior of your keyboard using hotkeys. -* [Combos](feature_combo.md) - Custom actions for multiple key holds. -* [Command](feature_command.md) - Runtime version of bootmagic (Formerly known as "Magic"). -* [Debounce API](feature_debounce_type.md) - Customization of debouncing algorithms, and the ability to add more/custom debouncing. -* [DIP Switch](feature_dip_switch.md) - Toggle switches for customizing board function. -* [Dynamic Macros](feature_dynamic_macros.md) - Record and playback macros from the keyboard itself. -* [Encoders](feature_encoders.md) - Rotary encoders! -* [Grave Escape](feature_grave_esc.md) - Lets you use a single key for Esc and Grave. -* [Haptic Feedback](feature_haptic_feedback.md) - Add haptic feedback drivers to your board. -* [HD44780 LCD Display](feature_hd44780.md) - Support for LCD character displays using the HD44780 standard. -* [Key Lock](feature_key_lock.md) - Lock a key in the "down" state. -* [Layouts](feature_layouts.md) - Use one keymap with any keyboard that supports your layout. -* [Leader Key](feature_leader_key.md) - Tap the leader key followed by a sequence to trigger custom behavior. -* [LED Matrix](feature_led_matrix.md) - LED Matrix single color lights for per key lighting (Single Color, not RGB). -* [Macros](feature_macros.md) - Send multiple key presses when pressing only one physical key. -* [Mouse keys](feature_mouse_keys.md) - Control your mouse pointer from your keyboard. -* [OLED Driver](feature_oled_driver.md) - Add OLED screens to your keyboard. -* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys) - Sticky Keys, lets you hit a key rather than holding it. -* [Pointing Device](feature_pointing_device.md) - Framework for connecting your custom pointing device to your keyboard. -* [PS2 Mouse](feature_ps2_mouse.md) - Driver for connecting a PS/2 mouse directly to your keyboard. -* [RGB Light](feature_rgblight.md) - RGB lighting for your keyboard. -* [RGB Matrix](feature_rgb_matrix.md) - RGB Matrix lights for per key lighting. -* [Space Cadet](feature_space_cadet.md) - Use your left/right shift keys to type parenthesis and brackets. -* [Split Keyboard](feature_split_keyboard.md) -* [Stenography](feature_stenography.md) - Put your keyboard into Plover mode for stenography use. -* [Swap Hands](feature_swap_hands.md) - Mirror your keyboard for one handed usage. -* [Tap Dance](feature_tap_dance.md) - Make a single key do as many things as you want. -* [Terminal](feature_terminal.md) - CLI interface to the internals of your keyboard. -* [Thermal Printer](feature_thermal_printer.md) - Connect a thermal printer to your keyboard to be able to toggle on a printed log of everything you type. -* [Unicode](feature_unicode.md) - Unicode input support. -* [Userspace](feature_userspace.md) - Share code between different keymaps and keyboards. -* [Velocikey](feature_velocikey.md) - Allows changes in RGB animation speed based on WPM/Typing speed. diff --git a/docs/flashing.md b/docs/flashing.md index 98841c1aacd7..ab003308d050 100644 --- a/docs/flashing.md +++ b/docs/flashing.md @@ -1,8 +1,8 @@ # Flashing Instructions and Bootloader Information -There are quite a few different types of bootloaders that keyboards use, and just about all of the use a different flashing method. Luckily, projects like the [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) aim to be compatible with all the different types without having to think about it much, but this article will describe the different types of bootloaders, and available methods for flashing them. +There are quite a few different types of bootloaders that keyboards use, and just about all of them use a different flashing method. Luckily, projects like the [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) aim to be compatible with all the different types without having to think about it much, but this article will describe the different types of bootloaders, and available methods for flashing them. -If you have a bootloader selected with the `BOOTLOADER` variable in your `rules.mk`, QMK will automatically calculate if your .hex file is the right size to be flashed to the device, and output the total size in bytes (along with the max). To run this process manually, compile with the target `check-size`, eg `make planck/rev4:default:check-size`. +If you have a bootloader selected with the `BOOTLOADER` variable in your `rules.mk`, QMK will automatically calculate if your .hex file is the right size to be flashed to the device, and output the total size in bytes (along with the max). ## DFU @@ -100,7 +100,7 @@ or make ::avrdude -#### Caterina commands +### Caterina commands There are a number of DFU commands that you can use to flash firmware to a DFU device: @@ -113,7 +113,7 @@ There are a number of DFU commands that you can use to flash firmware to a DFU d ## Halfkay -Halfkay is a super-slim protocol developed by PJRC that uses HID, and come on all Teensys (namely the 2.0). +Halfkay is a super-slim protocol developed by PJRC that uses HID, and comes on all Teensys (namely the 2.0). To ensure compatibility with the Halfkay bootloader, make sure this block is present your `rules.mk`: diff --git a/docs/fr-fr/_summary.md b/docs/fr-fr/_summary.md index 38e3abe7c7dd..bb14d2f0ad28 100644 --- a/docs/fr-fr/_summary.md +++ b/docs/fr-fr/_summary.md @@ -81,7 +81,7 @@ * [Macros](fr-fr/feature_macros.md) * [Boutons de souris](fr-fr/feature_mouse_keys.md) * [Pilotes / Drivers OLED](fr-fr/feature_oled_driver.md) - * [Touche one-shot](fr-fr/feature_advanced_keycodes.md#one-shot-keys) + * [Touche one-shot](fr-fr/one_shot_keys.md) * [Périphériques de pointage](fr-fr/feature_pointing_device.md) * [Souris PS/2](fr-fr/feature_ps2_mouse.md) * [Éclairage RGB](fr-fr/feature_rgblight.md) @@ -112,7 +112,7 @@ * Autres sujets * [Utiliser Eclipse avec QMK](fr-fr/other_eclipse.md) * [Utiliser VSCode avec QMK](fr-fr/other_vscode.md) - * [Support](fr-fr/support.md) + * [Support](fr-fr/getting_started_getting_help.md) * [Comment ajouter des traductions](fr-fr/translating.md) * À l’intérieur de QMK (En cours de documentation) diff --git a/docs/fr-fr/newbs_building_firmware_configurator.md b/docs/fr-fr/newbs_building_firmware_configurator.md index 577e5c80e9d4..d06242f39274 100644 --- a/docs/fr-fr/newbs_building_firmware_configurator.md +++ b/docs/fr-fr/newbs_building_firmware_configurator.md @@ -4,7 +4,7 @@ Le [Configurateur de QMK](https://config.qmk.fm) est une interface graphique en ?> **S'il vous plaît, suivez les étapes suivantes dans l'ordre.** -Regardez le [Tutoriel vidéo](https://youtu.be/tx54jkRC9ZY) +Regardez le [Tutoriel vidéo](https://youtu.be/tx54jkRC9ZY)https://www.youtube.com/watch?v=-imgglzDMdY) Le configurateur de QMK fonctionne mieux avec Chrome et Firefox. diff --git a/docs/getting_started_build_tools.md b/docs/getting_started_build_tools.md deleted file mode 100644 index fea20e59b4dd..000000000000 --- a/docs/getting_started_build_tools.md +++ /dev/null @@ -1,141 +0,0 @@ -# Installing Build Tools - -This page describes setting up the build environment for QMK. These instructions cover AVR processors (such as the atmega32u4). - - - -**Note:** If this is your first time here, check out the [Complete Newbs Guide](newbs.md) page. - -Before continuing, double check that your submodules (third-party libraries) are up to date by running `make git-submodule`. - -## Linux - -To ensure you are always up to date, you can just run `sudo util/qmk_install.sh`. That should always install all the dependencies needed. **This will run `apt-get upgrade`.** - -You can also install things manually, but this documentation might not be always up to date with all requirements. - -The current requirements are the following, but not all might be needed depending on what you do. Also note that some systems might not have all the dependencies available as packages, or they might be named differently. - -``` -build-essential -gcc -unzip -wget -zip -gcc-avr -binutils-avr -avr-libc -dfu-programmer -dfu-util -gcc-arm-none-eabi -binutils-arm-none-eabi -libnewlib-arm-none-eabi -git -``` - -Install the dependencies with your favorite package manager. - -Debian / Ubuntu example: - - sudo apt-get update - sudo apt-get install gcc unzip wget zip gcc-avr binutils-avr avr-libc dfu-programmer dfu-util gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi - -Fedora / Red Hat example: - - sudo dnf install gcc unzip wget zip dfu-util dfu-programmer avr-gcc avr-libc binutils-avr32-linux-gnu arm-none-eabi-gcc-cs arm-none-eabi-binutils-cs arm-none-eabi-newlib - -Arch / Manjaro example: - - pacman -S base-devel gcc unzip wget zip avr-gcc avr-binutils avr-libc dfu-util arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib git dfu-programmer dfu-util - -## Nix - -If you're on [NixOS](https://nixos.org/), or have Nix installed on Linux or macOS, run `nix-shell` from the repository root to get a build environment. - -By default, this will download compilers for both AVR and ARM. If you don't need both, disable the `avr` or `arm` arguments, e.g.: - - nix-shell --arg arm false - -## macOS -If you're using [Homebrew](http://brew.sh/), you can use the following commands: - - brew tap osx-cross/avr - brew tap osx-cross/arm - brew update - brew install avr-gcc@8 - brew link --force avr-gcc@8 - brew install dfu-programmer - brew install dfu-util - brew install arm-gcc-bin@8 - brew link --force arm-gcc-bin@8 - brew install avrdude - -This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line. Note that the `make` and `make install` portion during the homebrew installation of `avr-gcc@8` can take over 20 minutes and exhibit high CPU usage. - -## Windows with msys2 (recommended) - -The best environment to use, for Windows Vista through any later version (tested on 7 and 10), is [msys2](http://www.msys2.org). - -* Install msys2 by downloading it and following the instructions here: http://www.msys2.org -* Open the ``MSYS2 MingGW 64-bit`` shortcut -* Navigate to your QMK repository. For example, if it's in the root of your c drive: - * `$ cd /c/qmk_firmware` -* Run `util/qmk_install.sh` and follow the prompts - -## Windows 10 (deprecated) -These are the old instructions for Windows 10. We recommend you use [MSYS2 as outlined above](#windows-with-msys2-recommended). - -### Creators Update -If you have Windows 10 with Creators Update or later, you can build and flash the firmware directly. Before the Creators Update, only building was possible. If you don't have it yet or if are unsure, follow [these instructions](https://support.microsoft.com/en-us/instantanswers/d4efb316-79f0-1aa1-9ef3-dcada78f3fa0/get-the-windows-10-creators-update). - -### Windows Subsystem for Linux -In addition to the Creators Update, you need Windows 10 Subystem for Linux, so install it following [these instructions](http://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/). If you already have the Windows 10 Subsystem for Linux from the Anniversary update it's recommended that you [upgrade](https://betanews.com/2017/04/14/upgrade-windows-subsystem-for-linux/) it to 16.04LTS, because some keyboards don't compile with the toolchains included in 14.04LTS. Note that you need to know what your are doing if you chose the `sudo do-release-upgrade` method. - -### Git -If you already have cloned the repository on your Windows file system you can ignore this section. - -You will need to clone the repository to your Windows file system using the normal Git for Windows and **not** the WSL Git. So if you haven't installed Git before, [download](https://git-scm.com/download/win) and install it. Then [set it up](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup), it's important that you setup the e-mail and user name, especially if you are planning to contribute. - -Once Git is installed, open the Git Bash command and change the directory to where you want to clone QMK; note that you have to use forward slashes, and that your c drive is accessed like this `/c/path/to/where/you/want/to/go`. Then run `git clone --recurse-submodules https://github.com/qmk/qmk_firmware`, this will create a new folder `qmk_firmware` as a subfolder of the current one. - -### Toolchain Setup -The Toolchain setup is done through the Windows Subsystem for Linux, and the process is fully automated. If you want to do everything manually, there are no other instructions than the scripts themselves, but you can always open issues and ask for more information. - -1. Open "Bash On Ubuntu On Windows" from the start menu. -2. Go to the directory where you cloned `qmk_firmware`. Note that the paths start with `/mnt/` in the WSL, so you have to write for example `cd /mnt/c/path/to/qmk_firmware`. -3. Run `util/wsl_install.sh` and follow the on-screen instructions. -4. Close the Bash command window, and re-open it. -5. You are ready to compile and flash the firmware! - -### Some Important Things to Keep in Mind -* You can run `util/wsl_install.sh` again to get all the newest updates. -* Your QMK repository need to be on a Windows file system path, since WSL can't run executables outside it. -* The WSL Git is **not** compatible with the Windows Git, so use the Windows Git Bash or a windows Git GUI for all Git operations -* You can edit files either inside WSL or normally using Windows, but note that if you edit makefiles or shell scripts, make sure you are using an editor that saves the files with Unix line endings. Otherwise the compilation might not work. - -## Docker - -If this is a bit complex for you, Docker might be the turnkey solution you need. After installing [Docker CE](https://docs.docker.com/install/#supported-platforms), run the following command from the `qmk_firmware` directory to build a keyboard/keymap: -```bash -util/docker_build.sh keyboard:keymap -# For example: util/docker_build.sh ergodox_ez:steno -``` -This will compile the desired keyboard/keymap and leave the resulting `.hex` or `.bin` file in the QMK directory for you to flash. If `:keymap` is omitted, all keymaps are used. Note that the parameter format is the same as when building with `make`. - -You can also start the script without any parameters, in which case it will ask you to input the build parameters one by one, which you may find easier to use: -```bash -util/docker_build.sh -# Reads parameters as input (leave blank for all keyboards/keymaps) -``` - -There is also support for building _and_ flashing the keyboard straight from Docker by specifying the `target` as well: -```bash -util/docker_build.sh keyboard:keymap:target -# For example: util/docker_build.sh planck/rev6:default:flash -``` -If you're on Linux, this should work out of the box. On Windows and macOS, it requires [Docker Machine](http://gw.tnode.com/docker/docker-machine-with-usb-support-on-windows-macos/) to be running. This is tedious to set up, so it's not recommended; use [QMK Toolbox](https://github.com/qmk/qmk_toolbox) instead. - -!> Docker for Windows requires [Hyper-V](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v) to be enabled. This means that it cannot work on versions of Windows which don't have Hyper-V, such as Windows 7, Windows 8 and **Windows 10 Home**. - -## Vagrant -If you have any problems building the firmware, you can try using a tool called Vagrant. It will set up a virtual computer with a known configuration that's ready-to-go for firmware building. OLKB does NOT host the files for this virtual computer. Details on how to set up Vagrant are in the [vagrant guide](getting_started_vagrant.md). diff --git a/docs/getting_started_getting_help.md b/docs/getting_started_getting_help.md deleted file mode 100644 index 9788ad38e8c5..000000000000 --- a/docs/getting_started_getting_help.md +++ /dev/null @@ -1,15 +0,0 @@ -# Getting Help - -There are a lot of resources for getting help with QMK. - -## Realtime Chat - -You can find QMK developers and users on our main [Discord server](https://discord.gg/Uq7gcHh). There are specific channels in the server for chatting about the firmware, Toolbox, hardware, and configurator. - -## OLKB Subreddit - -The official QMK forum is [/r/olkb](https://reddit.com/r/olkb) on [reddit.com](https://reddit.com). - -## Github Issues - -You can open an [issue on GitHub](https://github.com/qmk/qmk_firmware/issues). This is especially handy when your issue will require long-term discussion or debugging. diff --git a/docs/hand_wire.md b/docs/hand_wire.md index 0e750f160a98..0c5b4f45f4df 100644 --- a/docs/hand_wire.md +++ b/docs/hand_wire.md @@ -1,114 +1,5 @@ # Hand-Wiring Guide -## Preamble: How a Keyboard Matrix Works (and why we need diodes) - -The collapsible section below covers why keyboards are wired the way they are, as outlined in this guide. It isn't required reading to make your own hand wired keyboard, but provides background information. - -
- -Click for details - -Without a matrix circuit each switch would require its own wire directly to the controller. - -Simply put, when the circuit is arranged in rows and columns, if a key is pressed, a column wire makes contact with a row wire and completes a circuit. The keyboard controller detects this closed circuit and registers it as a key press. - -The microcontroller will be setup up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example: - - Column 0 being scanned Column 1 being scanned - x x - col0 col1 col0 col1 - | | | | - row0 ---(key0)---(key1) row0 ---(key0)---(key1) - | | | | - row1 ---(key2)---(key3) row1 ---(key2)---(key3) - -The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column. - -When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected: - - Column 0 being scanned Column 1 being scanned - x x - col0 col1 col0 col1 - | | | | - x row0 ---(-+-0)---(key1) row0 ---(-+-0)---(key1) - | | | | - row1 ---(key2)---(key3) row1 ---(key2)---(key3) - -We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is - - col0: 0b01 - col1: 0b00 - │└row0 - └row1 - -A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious: - - Column 0 being scanned Column 1 being scanned - x x - col0 col1 col0 col1 - | | | | - x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1) - | | | | - x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3) - - Remember that this ^ is still connected to row1 - -The data we get from that is: - - col0: 0b11 - col1: 0b11 - │└row0 - └row1 - -Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this; - - Column 0 being scanned Column 1 being scanned - x x - col0 col1 col0 col1 - │ │ | │ - (key0) (key1) (key0) (key1) - ! │ ! │ ! | ! │ - row0 ─────┴────────┘ │ row0 ─────┴────────┘ │ - │ │ | │ - (key2) (key3) (key2) (key3) - ! ! ! ! - row1 ─────┴────────┘ row1 ─────┴────────┘ - -In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|` - -Now when we press the three keys, invoking what would be a ghosting scenario: - - Column 0 being scanned Column 1 being scanned - x x - col0 col1 col0 col1 - │ │ │ │ - (┌─┤0) (┌─┤1) (┌─┤0) (┌─┤1) - ! │ ! │ ! │ ! │ - x row0 ─────┴────────┘ │ x row0 ─────┴────────┘ │ - │ │ │ │ - (key2) (┌─┘3) (key2) (┌─┘3) - ! ! ! ! - row1 ─────┴────────┘ x row1 ─────┴────────┘ - -Things act as they should! Which will get us the following data: - - col0: 0b01 - col1: 0b11 - │└row0 - └row1 - -The firmware can then use this correct data to detect what it should do, and eventually, what signals it needs to send to the OS. - -Further reading: -- [Wikipedia article](https://en.wikipedia.org/wiki/Keyboard_matrix_circuit) -- [Deskthority article](https://deskthority.net/wiki/Keyboard_matrix) -- [Keyboard Matrix Help by Dave Dribin (2000)](https://www.dribin.org/dave/keyboard/one_html/) -- [How Key Matrices Works by PCBheaven](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) (animated examples) -- [How keyboards work - QMK documentation](how_keyboards_work.md) - -
- - ## Parts list You will need: (where *x* is the number of keys on your planned keyboard) @@ -141,29 +32,29 @@ Start by installing the switches and stabilisers in the plate. Depending on the If you are following a pre-existing handwire guide (e.g. for the keyboards in the [handwire firmware section](https://github.com/qmk/qmk_firmware/tree/master/keyboards/handwired) you can skip this step, just ensure you wire the matrix as described. -What you want to achieve is one leg from each switch being attached to the corresponding switches next to it (rows) and the other leg being attached to the switches above and below it (columns) and a diode to one of the legs, mosy commonly this will be the leg attached to the rows, and the diode will face away from it (Column to Row) i.e. with the wire furthest from the black line on the diode connected to the switch (as current will only travel in one direction through a diode) +What you want to achieve is one leg from each switch being attached to the corresponding switches next to it (rows) and the other leg being attached to the switches above and below it (columns) and a diode to one of the legs, mosy commonly this will be the leg attached to the rows, and the diode will face away from it (Column to Row) i.e. with the wire furthest from the black line on the diode connected to the switch (as current will only travel in one direction through a diode). It is fairly simple to plan for an ortholinear keyboard (like a Planck). -![Example planck matrix](https://i.imgur.com/FRShcLD.png) +![Example Planck matrix](https://i.imgur.com/FRShcLD.png) Image from [RoastPotatoes' "How to hand wire a Planck"](https://blog.roastpotatoes.co/guide/2015/11/04/how-to-handwire-a-planck/) But the larger and more complicated your keyboard, the more complex the matrix. [Keyboard Firmware Builder](https://kbfirmware.com/) can help you plan your matrix layout (shown here with a basic fullsize ISO keyboard imported from [Keyboard Layout Editor](http://www.keyboard-layout-editor.com). ![Example ISO matrix](https://i.imgur.com/UlJ4ZDP.png) - Bear in mind that the number of rows plus the number of columns can not exceed the number of I/O pins on your controller. So the fullsize matrix shown above would be possible on a Proton C or Teensy++, but not on a regular Teensy or Pro Micro +Bear in mind that the number of rows plus the number of columns can not exceed the number of I/O pins on your controller. So the fullsize matrix shown above would be possible on a Proton C or Teensy++, but not on a regular Teensy or Pro Micro. -#### Common Microcontroller Boards +### Common Microcontroller Boards | Board | Controller | # I/O | Pinout | | :------------ |:-------------:| ------:| ------ | -| Pro Micro* | ATmega32u4 | 20 | [link](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro#Teensy++_2.0) | +| Pro Micro* | ATmega32u4 | 20 | [link](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro#Teensy++_2.0) | | Teensy 2.0 | ATmega32u4 | 25 | [link](https://www.pjrc.com/teensy/pinout.html) | | [QMK Proton C](https://qmk.fm/proton-c/) | STM32F303xC | 36 | [link 1](https://i.imgur.com/RhtrAlc.png), [2](https://deskthority.net/wiki/QMK_Proton_C) | | Teensy++ 2.0 | AT90USB1286 | 46 | [link](https://www.pjrc.com/teensy/pinout.html#Teensy_2.0) | -*Elite C is essentially the same as a pro micro with a USB-C instead of Micro-USB +*Elite C is essentially the same as a Pro Micro with a USB-C instead of Micro-USB There are also a number of boards designed specifically for handwiring that mount directly to a small number of switches and offer pinouts for the rest. Though these are generally more expensive and may be more difficult to get hold of. @@ -204,7 +95,7 @@ If you are planning a split keyboard (e.g. Dactyl) each half will require a cont There are a lot of soldering guides and tips available elsewhere but here are some of the most useful and relevant for hand wiring: -To ensure a strong solder joint you want a good amount of contact between the solder and the 2 peices of metal you are connecting, a good way of doing this (though not required) is looping around pins or twisting wires together before applying solder. +To ensure a strong solder joint you want a good amount of contact between the solder and the two pieces of metal you are connecting. A good way of doing this (though not required) is looping around pins or twisting wires together before applying solder. Looped around rod Looped diode leg @@ -220,24 +111,11 @@ When you come to apply the solder, hold the soldering iron against the two surfa Don't hold the iron on the solder/joint longer than necessary. Heat will be conducted through the surfaces and can damage components (melt switch housings etc.). Also, solder contains flux, which aids in ["wetting"](https://en.m.wikipedia.org/wiki/Wetting). The longer heat is applied to the solder the more flux will evaporate meaning you may end up with a bad solder joint with peaks which, apart from looking bad, may also increase the risk of electrical shorts. -The following collapsible section describes in detail how to solder rows using the bent diode technique and columns using short lengths of wire. - -
- -Click for details +#### Soldering the Diodes -## Soldering the Diodes +Starting at the top-left switch, place the diode (with tweezers if you have them) on the switch so that the diode itself is vertically aligned, and the black line is facing toward you. The input lead of the diode should be touching the left contact on the switch, and the bent, output end should be facing to the right and resting on the switch there, like this: -Starting at the top-left switch, place the diode (with tweezers if you have them) on the switch so that the diode itself is vertically aligned, and the black line is facing toward you. The straight end of the diode should be touching the left contact on the switch, and the bent end should be facing to the right and resting on the switch there, like this: - -``` - │o - ┌┴┐ o - │ │ O - ├─┤ - └┬┘ - └───────────── -``` +![soldering-diodes-01.png](https://raw.githubusercontent.com/noroadsleft/qmk_images/master/docs/hand_wire/soldering-diodes-01.png) Letting the diode rest, grab your solder, and touch both it and the soldering iron to the left contact at the same time - the rosin in the solder should make it easy for the solder to flow over both the diode and the keyswitch contact. The diode may move a little, and if it does, carefully position it back it place by grabbing the bent end of the diode - the other end will become hot very quickly. If you find that it's moving too much, using needle-nose pliers of some sort may help to keep the diode still when soldering. @@ -247,20 +125,13 @@ After soldering things in place, it may be helpful to blow on the joint to push When the first diode is complete, the next one will need to be soldered to both the keyswitch, and the previous diode at the new elbow. That will look something like this: -``` - │o │o - ┌┴┐ o ┌┴┐ o - │ │ O │ │ O - ├─┤ ├─┤ - └┬┘ └┬┘ - └────────────────┴───────────── -``` +![soldering-diodes-02.png](https://raw.githubusercontent.com/noroadsleft/qmk_images/master/docs/hand_wire/soldering-diodes-02.png) After completing a row, use the wire cutters to trim the excess wire from the tops of the diodes, and from the right side on the final switch. This process will need to completed for each row you have. When all of the diodes are completely soldered, it's a good idea to quickly inspect each one to ensure that your solder joints are solid and sturdy - repairing things after this is possible, but more difficult. -## Soldering the Columns +#### Soldering the Columns You'll have some options in the next process - it's a good idea to insulate the column wires (since the diodes aren't), but if you're careful enough, you can use exposed wires for the columns - it's not recommended, though. If you're using single-cored wire, stripping the plastic off of the whole wire and feeding it back on is probably the best option, but can be difficult depending on the size and materials. You'll want to leave parts of the wire exposed where you're going to be solder it onto the keyswitch. @@ -270,9 +141,7 @@ Before beginning to solder, it helps to have your wire pre-bent (if using single If you're not using any insulation, you can try to keep the column wires elevated, and solder them near the tips of the keyswitch contacts - if the wires are sturdy enough, they won't short out to the row wiring an diodes. -
- -# Wiring up the controller +## Wiring up the controller Now that the matrix itself is complete, it's time to connect what you've done to the microcontroller board. @@ -280,15 +149,16 @@ Place the microcontroller where you want it to be located, give thought to mount Find the pinout/documentation for your microcontroller board ([links here](#common-microcontroller-boards)) and make a note of all the digital I/O pins on it (note that on some controllers, like the teensy, analogue I/O can double as digital) as these are the pins you want to connect your wires to. -
+---- -Specific instructions for the Teensy 2.0 +### Specific instructions for the Teensy 2.0 - There are some pins on the Teensy that are special, like D6 (the LED on the chip), or some of the UART, SPI, I2C, or PWM channels, but only avoid those if you're planning something in addition to a keyboard. If you're unsure about wanting to add something later, you should have enough pins in total to avoid a couple. +There are some pins on the Teensy that are special, like D6 (the LED on the chip), or some of the UART, SPI, I2C, or PWM channels, but only avoid those if you're planning something in addition to a keyboard. If you're unsure about wanting to add something later, you should have enough pins in total to avoid a couple. The pins you'll absolutely have to avoid, as with any controller, are: GND, VCC, AREF, and RST - all the others are usable and accessible in the firmware. -
+---- + Cut wires to the length of the distance from the a point on each column/row to the controller. You can solder anywhere along the row, as long as it's after the diode - soldering before the diode (on the keyswitch side) will cause that row not to work. @@ -301,150 +171,32 @@ As you solder the wires to the controller make a note of which row/column is goi As you move along, be sure that the controller is staying in place - recutting and soldering the wires is a pain! - -# Getting Some Basic Firmware Set Up +## Getting Some Basic Firmware Set Up From here, you should have a working keyboard once you program a firmware. Simple firmware can be created easily using the [Keyboard Firmware Builder](https://kbfirmware.com/) website. Recreate your layout using [Keyboard Layout Editor](http://www.keyboard-layout-editor.com), import it and recreate the matrix (if not already done as part of [planning the matrix](#planning-the-matrix). -Go through the rest of the tabs, assigning keys until you get to the last one where you can compile and download your firmware. The .hex file can be flashed straight onto your keyboard, and the .zip of source files can be modified for advanced functionality and compiled locally using the method described in the collapsable section below, or using the more comprehensive [getting started guide.](newbs_getting_started) +Go through the rest of the tabs, assigning keys until you get to the last one where you can compile and download your firmware. The .hex file can be flashed straight onto your keyboard, and the .zip of source files can be modified for advanced functionality and compiled locally using the method described in [Building Your First Firmware](newbs_building_firmware?id=build-your-firmware). +The source given by Keyboard Firmware Builder is QMK, but is based on a version of QMK from early 2017. To compile the code from your .zip file in a modern version of QMK Firmware, you'll need to open the .zip and follow these instructions: -
- -Creating and compiling your firmware locally (command line method) - -To start out, download [the firmware](https://github.com/qmk/qmk_firmware/) - We'll be doing a lot from the Terminal/command prompt, so get that open, along with a decent text editor like [Sublime Text](http://www.sublimetext.com/) (paid) or [Visual Studio Code](https://code.visualstudio.com) (free). - -The first thing we're going to do is create a new keyboard. In your terminal, run this command, which will ask you some questions and generate a basic keyboard project: - -``` -./util/new_keyboard.sh -``` - -You'll want to navigate to the `keyboards//` folder by typing, like the print-out from the script specifies: - -``` -cd keyboards/ -``` - -### `config.h` - -The first thing you're going to want to modify is the `config.h` file. Find `MATRIX_ROWS` and `MATRIX_COLS` and change their definitions to match the dimensions of your keyboard's matrix. - -Farther down are `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`. Change their definitions to match how you wired up your matrix (looking from the top of the keyboard, the rows run top-to-bottom and the columns run left-to-right). Likewise, change the definition of `UNUSED_PINS` to match the pins you did not use (this will save power). - -### `.h` - -The next file you'll want to look at is `.h`. You're going to want to rewrite the `LAYOUT` definition - the format and syntax here is extremely important, so pay attention to how things are setup. The first half of the definition are considered the arguments - this is the format that you'll be following in your keymap later on, so you'll want to have as many k*xy* variables here as you do keys. The second half is the part that the firmware actually looks at, and will contain gaps depending on how you wired your matrix. - -We'll dive into how this will work with the following example. Say we have a keyboard like this: - -``` - ┌───┬───┬───┐ - │ │ │ │ - ├───┴─┬─┴───┤ - │ │ │ - └─────┴─────┘ -``` - -This can be described by saying the top row is 3 1u keys, and the bottom row is 2 1.5u keys. The difference between the two rows is important, because the bottom row has an unused column spot (3 v 2). Let's say that this is how we wired the columns: - -``` - ┌───┬───┬───┐ - │ ┋ │ ┋ │ ┋ │ - ├─┋─┴─┬─┴─┋─┤ - │ ┋ │ ┋ │ - └─────┴─────┘ -``` - -The middle column is unused on the bottom row in this example. Our `LAYOUT` definition would look like this: - -``` - #define LAYOUT( \ - k00, k01, k02, \ - k10, k11, \ - ) \ - { \ - { k00, k01, k02 }, \ - { k10, KC_NO, k11 }, \ - } -``` - -Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring. - -Let's say that instead, we wired our keyboard like this (a fair thing to do): - -``` - ┌───┬───┬───┐ - │ ┋ │ ┋│ ┋ │ - ├─┋─┴─┬┋┴───┤ - │ ┋ │┋ │ - └─────┴─────┘ -``` - -This would require our `LAYOUT` definition to look like this: - -``` - #define LAYOUT( \ - k00, k01, k02, \ - k10, k11, \ - ) \ - { \ - { k00, k01, k02 }, \ - { k10, k11, KC_NO }, \ +1. Extract the `kb` folder to `qmk_firmware/keyboards/handwired/`. +2. Open the extracted `kb` folder, then proceed to the `keymaps/default/` folder, and open `keymap.c`. +3. Locate and delete the `action_get_macro` code block: + ``` + const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { + ... + return MACRO_NONE; } -``` - -Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `LAYOUT` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it. - -### `keymaps//default.c` - -This is the actual keymap for your keyboard, and the main place you'll make changes as you perfect your layout. `default.c` is the file that gets pull by default when typing `make`, but you can make other files as well, and specify them by typing `make handwired/:`, which will pull `keymaps//keymap.c`. - -The basis of a keymap is its layers - by default, layer 0 is active. You can activate other layers, the highest of which will be referenced first. Let's start with our base layer. - -Using our previous example, let's say we want to create the following layout: - -``` - ┌───┬───┬───┐ - │ A │ 1 │ H │ - ├───┴─┬─┴───┤ - │ TAB │ SPC │ - └─────┴─────┘ -``` - -This can be accomplished by using the following `keymaps` definition: - -``` -const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - [0] = LAYOUT( /* Base */ - KC_A, KC_1, KC_H, \ - KC_TAB, KC_SPC \ - ), -}; -``` - -Note that the layout of the keycodes is similar to the physical layout of our keyboard - this make it much easier to see what's going on. A lot of the keycodes should be fairly obvious, but for a full list of them, check out [Keycodes](keycodes.md) - there are also a lot of aliases to condense your keymap file. - -It's also important to use the `LAYOUT` function we defined earlier - this is what allows the firmware to associate our intended readable keymap with the actual wiring. - -## Compiling Your Firmware - -After you've written out your entire keymap, you're ready to get the firmware compiled and onto your Teensy. Before compiling, you'll need to get your [development environment set-up](getting_started_build_tools.md) - you can skip the dfu-programmer instructions, but you'll need to download and install the [Teensy Loader](https://www.pjrc.com/teensy/loader.html) to get the firmware on your Teensy. - -Once everything is installed, running `make` in the terminal should get you some output, and eventually a `.hex` file in that folder. If you're having trouble with this step, see the end of the guide for the trouble-shooting section. - -Once you have your `.hex` file, open up the Teensy loader application, and click the file icon. From here, navigate to your `QMK/keyboards//` folder, and select the `.hex` file. Plug in your keyboard and press the button on the Teensy - you should see the LED on the device turn off once you do. The Teensy Loader app will change a little, and the buttons should be clickable - click the download button (down arrow), and then the reset button (right arrow), and your keyboard should be ready to go! - -
+ ``` +4. Save and close `keymap.c`. ## Flashing the Firmware -Install [QMK toolbox](https://github.com/qmk/qmk_toolbox). +Install [QMK Toolbox](https://github.com/qmk/qmk_toolbox). -![QMK Toolbox](https://i.imgur.com/86Cz30H.png) +![QMK Toolbox](https://raw.githubusercontent.com/noroadsleft/qmk_images/master/docs/hand_wire/qmk_toolbox.png "QMK Toolbox 0.0.16 on Windows 8.1") Under "Local File" navigate to your newly created .hex file. Under "Microcontroller", select the corresponding one for your controller board (common ones available [here](#common-microcontroller-boards)). @@ -453,20 +205,20 @@ Plug in your keyboard and press the reset button (or short the Reset and Ground ## Testing Your Firmware -Use a website such as [keyboard tester](https://www.keyboardtester.com/tester.html)/[keyboard checker](http://keyboardchecker.com/) or just open a text editor and try typing - you should get the characters that you put into your keymap. Test each key, and make a note of the ones that aren't working. Here's a quick trouble-shooting guide for non-working keys: +Use a website such as [QMK Configurator's Keyboard Tester](https://config.qmk.fm/#/test), [Keyboard Tester](https://www.keyboardtester.com/tester.html), or [Keyboard Checker](http://keyboardchecker.com/) or just open a text editor and try typing - you should get the characters that you put into your keymap. Test each key, and make a note of the ones that aren't working. Here's a quick trouble-shooting guide for non-working keys: -0. Flip the keyboard back over and short the keyswitch's contacts with a piece wire - this will eliminate the possibility of the keyswitch being bad and needing to be replaced. -1. Check the solder points on the keyswitch - these need to be plump and whole. If you touch it with a moderate amount of force and it comes apart, it's not strong enough. -2. Check the solder joints on the diode - if the diode is loose, part of your row may register, while the other may not. -3. Check the solder joints on the columns - if your column wiring is loose, part or all of the column may not work. -4. Check the solder joints on both sides of the wires going to/from the Teensy - the wires need to be fully soldered and connect to both sides. -5. Check the `.h` file for errors and incorrectly placed `KC_NO`s - if you're unsure where they should be, instead duplicate a k*xy* variable. -6. Check to make sure you actually compiled the firmware and flashed the Teensy correctly. Unless you got error messages in the terminal, or a pop-up during flashing, you probably did everything correctly. -7. Use a multimeter to check that the switch is actually closing when actuated (completing the circuit when pressed down). +1. Flip the keyboard back over and short the keyswitch's contacts with a piece wire - this will eliminate the possibility of the keyswitch being bad and needing to be replaced. +2. Check the solder points on the keyswitch - these need to be plump and whole. If you touch it with a moderate amount of force and it comes apart, it's not strong enough. +3. Check the solder joints on the diode - if the diode is loose, part of your row may register, while the other may not. +4. Check the solder joints on the columns - if your column wiring is loose, part or all of the column may not work. +5. Check the solder joints on both sides of the wires going to/from the Teensy - the wires need to be fully soldered and connect to both sides. +6. Check the `.h` file for errors and incorrectly placed `KC_NO`s - if you're unsure where they should be, instead duplicate a k*xy* variable. +7. Check to make sure you actually compiled the firmware and flashed the Teensy correctly. Unless you got error messages in the terminal, or a pop-up during flashing, you probably did everything correctly. +8. Use a multimeter to check that the switch is actually closing when actuated (completing the circuit when pressed down). If you've done all of these things, keep in mind that sometimes you might have had multiple things affecting the keyswitch, so it doesn't hurt to test the keyswitch by shorting it out at the end. -# Finishing up +## Finishing up Once you have confirmed that the keyboard is working, if you have used a seperate (non handwire specific) controller you will want to secure it in place. This can be done in many different ways e.g. hot glue, double sided sticky tape, 3D printed caddy, electrical tape. @@ -474,7 +226,7 @@ If you found this fullfilling you could experiment by adding additional features There are a lot of possibilities inside the firmware - explore [docs.qmk.fm](http://docs.qmk.fm) for a full feature list, and dive into the different keyboards to see how people use all of them. You can always stop by [the OLKB subreddit](http://reddit.com/r/olkb) or [QMK Discord](https://discord.gg/Uq7gcHh) for help! -# Links to other guides: +## Links to Other Guides - [matt3o's step by step guide (BrownFox build)](https://deskthority.net/viewtopic.php?f=7&t=6050) also his [website](https://matt3o.com/hand-wiring-a-custom-keyboard/) and [video guide](https://www.youtube.com/watch?v=LVzpsjFWPP4) - [Cribbit's "Modern hand wiring guide - stronger, cleaner, easier"](https://geekhack.org/index.php?topic=87689.0) @@ -483,4 +235,10 @@ There are a lot of possibilities inside the firmware - explore [docs.qmk.fm](htt - [Masterzen's "Handwired keyboard build log"](http://www.masterzen.fr/2018/12/16/handwired-keyboard-build-log-part-1/) +# Legacy Content + +This page used to include more content. We have moved a section that used to be part of this page its own page. Everything below this point is simply a redirect so that people following old links on the web find what they're looking for. + +## Preamble: How a Keyboard Matrix Works (and why we need diodes) :id=preamble-how-a-keyboard-matrix-works-and-why-we-need-diodes +* [How a Keyboard Matrix Works](how_a_matrix_works.md) diff --git a/docs/hardware.md b/docs/hardware.md deleted file mode 100644 index c3cc0e591eac..000000000000 --- a/docs/hardware.md +++ /dev/null @@ -1,8 +0,0 @@ -# Hardware - -QMK runs on a variety of hardware. If your processor can be targeted by [LUFA](http://www.fourwalledcubicle.com/LUFA.php) or [ChibiOS](http://www.chibios.com) you can probably get QMK running on it. This section explores getting QMK running on, and communicating with, hardware of all kinds. - -* [Keyboard Guidelines](hardware_keyboard_guidelines.md) -* [AVR Processors](hardware_avr.md) -* ARM Processors (TBD) -* [Drivers](hardware_drivers.md) diff --git a/docs/hardware_keyboard_guidelines.md b/docs/hardware_keyboard_guidelines.md index 5d9968f6d724..a862bc0ca88b 100644 --- a/docs/hardware_keyboard_guidelines.md +++ b/docs/hardware_keyboard_guidelines.md @@ -61,10 +61,76 @@ This file is used by the [QMK API](https://github.com/qmk/qmk_api). It contains All projects need to have a `config.h` file that sets things like the matrix size, product name, USB VID/PID, description and other settings. In general, use this file to set essential information and defaults for your keyboard that will always work. +The `config.h` files can also be placed in sub-folders, and the order in which they are read is as follows: + +* `keyboards/top_folder/config.h` + * `keyboards/top_folder/sub_1/config.h` + * `keyboards/top_folder/sub_1/sub_2/config.h` + * `keyboards/top_folder/sub_1/sub_2/sub_3/config.h` + * `keyboards/top_folder/sub_1/sub_2/sub_3/sub_4/config.h` + * `users/a_user_folder/config.h` + * `keyboards/top_folder/keymaps/a_keymap/config.h` + * `keyboards/top_folder/sub_1/sub_2/sub_3/sub_4/post_config.h` + * `keyboards/top_folder/sub_1/sub_2/sub_3/post_config.h` + * `keyboards/top_folder/sub_1/sub_2/post_config.h` + * `keyboards/top_folder/sub_1/post_config.h` +* `keyboards/top_folder/post_config.h` + +The `post_config.h` file can be used for additional post-processing, depending on what is specified in the `config.h` file. For example, if you define the `IOS_DEVICE_ENABLE` macro in your keymap-level `config.h` file as follows, you can configure more detailed settings accordingly in the `post_config.h` file: + +* `keyboards/top_folder/keymaps/a_keymap/config.h` + ```c + #define IOS_DEVICE_ENABLE + ``` +* `keyboards/top_folder/post_config.h` + ```c + #ifndef IOS_DEVICE_ENABLE + // USB_MAX_POWER_CONSUMPTION value for this keyboard + #define USB_MAX_POWER_CONSUMPTION 400 + #else + // fix iPhone and iPad power adapter issue + // iOS device need lessthan 100 + #define USB_MAX_POWER_CONSUMPTION 100 + #endif + + #ifdef RGBLIGHT_ENABLE + #ifndef IOS_DEVICE_ENABLE + #define RGBLIGHT_LIMIT_VAL 200 + #define RGBLIGHT_VAL_STEP 17 + #else + #define RGBLIGHT_LIMIT_VAL 35 + #define RGBLIGHT_VAL_STEP 4 + #endif + #ifndef RGBLIGHT_HUE_STEP + #define RGBLIGHT_HUE_STEP 10 + #endif + #ifndef RGBLIGHT_SAT_STEP + #define RGBLIGHT_SAT_STEP 17 + #endif + #endif + ``` + +?> If you define options using `post_config.h` as in the above example, you should not define the same options in the keyboard- or user-level `config.h`. + ### `rules.mk` The presence of this file means that the folder is a keyboard target and can be used in `make` commands. This is where you setup the build environment for your keyboard and configure the default set of features. +The `rules.mk` file can also be placed in a sub-folder, and its reading order is as follows: + +* `keyboards/top_folder/rules.mk` + * `keyboards/top_folder/sub_1/rules.mk` + * `keyboards/top_folder/sub_1/sub_2/rules.mk` + * `keyboards/top_folder/sub_1/sub_2/sub_3/rules.mk` + * `keyboards/top_folder/sub_1/sub_2/sub_3/sub_4/rules.mk` + * `keyboards/top_folder/keymaps/a_keymap/rules.mk` + * `users/a_user_folder/rules.mk` +* `common_features.mk` + +Many of the settings written in the `rules.mk` file are interpreted by `common_features.mk`, which sets the necessary source files and compiler options. + +?> See `build_keyboard.mk` and `common_features.mk` for more details. + ### `` This is where you will write custom code for your keyboard. Typically you will write code to initialize and interface with the hardware in your keyboard. If your keyboard consists of only a key matrix with no LEDs, speakers, or other auxiliary hardware this file can be blank. diff --git a/docs/he-il/_summary.md b/docs/he-il/_summary.md index 804db534a34b..21059f997aa8 100644 --- a/docs/he-il/_summary.md +++ b/docs/he-il/_summary.md @@ -93,7 +93,7 @@ * [Macros](he-il/feature_macros.md) * [Mouse Keys](he-il/feature_mouse_keys.md) * [OLED Driver](he-il/feature_oled_driver.md) - * [One Shot Keys](he-il/feature_advanced_keycodes.md#one-shot-keys) + * [One Shot Keys](he-il/one_shot_keys.md) * [Pointing Device](he-il/feature_pointing_device.md) * [PS/2 Mouse](he-il/feature_ps2_mouse.md) * [RGB Lighting](he-il/feature_rgblight.md) @@ -124,7 +124,7 @@ * נושאים נוספים * [שימוש ב - Eclipse עם QMK](he-il/other_eclipse.md) * [שימוש ב - VSCode עם QMK](he-il/other_vscode.md) - * [תמיכה](he-il/support.md) + * [תמיכה](he-il/getting_started_getting_help.md) * [כיצד להוסיף תרגום](he-il/translating.md) * QMK מבפנים (בתהליך) diff --git a/docs/he-il/becoming_a_qmk_collaborator.md b/docs/he-il/becoming_a_qmk_collaborator.md deleted file mode 100644 index 4c14441bdb26..000000000000 --- a/docs/he-il/becoming_a_qmk_collaborator.md +++ /dev/null @@ -1,11 +0,0 @@ -
-# איך להפוך לשותף של QMK - -שותף של QMK הוא יצרן מקלדות או מעצב שמעוניין בלעזור ל-QMK לגדול ולתמוך במקלד(ו)ת שלהם, ולעודד את המשתמשים והצרכנים להוסיף יכולות, רעיונות ומיפויים. אנחנו תמיד מחפשים עוד מקלדות ומשתפי פעולה, אבל אנחנו מבקשים שיעמדו בדרישות הבאות: - -* **קיום לוח PCB למכירה.** לצערינו, יש יותר מידי הסתבכויות ובעיות עם מקלדות המחווטות ידנית. -* **תחזוק המקלדת ב-QMK.** זה אולי רק ידרוש הגדרה בסיסית כדי לגרום למקלדת לעבוד, אבל זה גם יכול לכלול התאמה של שינויים בקוד הליבה של QMK שיכול לשבור קוד ייחודי שלכם. -* **אישור ומיזוג Pull Requests של מיפויי מקלדת עבור המקלדת** אנחנו רוצים לעודד משתמשים לתרום את מיפויי המקלדת שלהם לאחרים כדי לעזור לאחרים להתחיל ליצור את שלהם. - -אם אתם עומדים בדרישות הללו, שלחו לנו מייל לכתובת hello@qmk.fm עם מבוא וקישורים עבור המקלדת שלכם. -
\ No newline at end of file diff --git a/docs/how_a_matrix_works.md b/docs/how_a_matrix_works.md new file mode 100644 index 000000000000..df7d164cbbbc --- /dev/null +++ b/docs/how_a_matrix_works.md @@ -0,0 +1,99 @@ +# How a Keyboard Matrix Works + +Keyboard switch matrices are arranged in rows and columns. Without a matrix circuit, each switch would require its own wire directly to the controller. + +When the circuit is arranged in rows and columns, if a key is pressed, a column wire makes contact with a row wire and completes a circuit. The keyboard controller detects this closed circuit and registers it as a key press. + +The microcontroller will be set up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example: + + Column 0 being scanned Column 1 being scanned + x x + col0 col1 col0 col1 + | | | | + row0 ---(key0)---(key1) row0 ---(key0)---(key1) + | | | | + row1 ---(key2)---(key3) row1 ---(key2)---(key3) + +The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column. + +When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected: + + Column 0 being scanned Column 1 being scanned + x x + col0 col1 col0 col1 + | | | | + x row0 ---(-+-0)---(key1) row0 ---(-+-0)---(key1) + | | | | + row1 ---(key2)---(key3) row1 ---(key2)---(key3) + +We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is: + + col0: 0b01 + col1: 0b00 + │└row0 + └row1 + +A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious: + + Column 0 being scanned Column 1 being scanned + x x + col0 col1 col0 col1 + | | | | + x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1) + | | | | + x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3) + + Remember that this ^ is still connected to row1 + +The data we get from that is: + + col0: 0b11 + col1: 0b11 + │└row0 + └row1 + +Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this; + + Column 0 being scanned Column 1 being scanned + x x + col0 col1 col0 col1 + │ │ | │ + (key0) (key1) (key0) (key1) + ! │ ! │ ! | ! │ + row0 ─────┴────────┘ │ row0 ─────┴────────┘ │ + │ │ | │ + (key2) (key3) (key2) (key3) + ! ! ! ! + row1 ─────┴────────┘ row1 ─────┴────────┘ + +In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|` + +Now when we press the three keys, invoking what would be a ghosting scenario: + + Column 0 being scanned Column 1 being scanned + x x + col0 col1 col0 col1 + │ │ │ │ + (┌─┤0) (┌─┤1) (┌─┤0) (┌─┤1) + ! │ ! │ ! │ ! │ + x row0 ─────┴────────┘ │ x row0 ─────┴────────┘ │ + │ │ │ │ + (key2) (┌─┘3) (key2) (┌─┘3) + ! ! ! ! + row1 ─────┴────────┘ x row1 ─────┴────────┘ + +Things act as they should! Which will get us the following data: + + col0: 0b01 + col1: 0b11 + │└row0 + └row1 + +The firmware can then use this correct data to detect what it should do, and eventually, what signals it needs to send to the OS. + +Further reading: +- [Wikipedia article](https://en.wikipedia.org/wiki/Keyboard_matrix_circuit) +- [Deskthority article](https://deskthority.net/wiki/Keyboard_matrix) +- [Keyboard Matrix Help by Dave Dribin (2000)](https://www.dribin.org/dave/keyboard/one_html/) +- [How Key Matrices Works by PCBheaven](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) (animated examples) +- [How keyboards work - QMK documentation](how_keyboards_work.md) diff --git a/docs/i2c_driver.md b/docs/i2c_driver.md index d5c340edce73..d28a20fa16a5 100644 --- a/docs/i2c_driver.md +++ b/docs/i2c_driver.md @@ -1,33 +1,46 @@ -# I2C Master Driver +# I2C Master Driver :id=i2c-master-driver The I2C Master drivers used in QMK have a set of common functions to allow portability between MCUs. -## Available functions +## An important note on I2C Addresses :id=note-on-i2c-addresses + +All of the addresses expected by this driver should be pushed to the upper 7 bits of the address byte. Setting +the lower bit (indicating read/write) will be done by the respective functions. Almost all I2C addresses listed +on datasheets and the internet will be represented as 7 bits occupying the lower 7 bits and will need to be +shifted to the left (more significant) by one bit. This is easy to do via the bitwise shift operator `<< 1`. + +You can either do this on each call to the functions below, or once in your definition of the address. For example if your device has an address of `0x18`: + +`#define MY_I2C_ADDRESS (0x18 << 1)` + +See https://www.robot-electronics.co.uk/i2c-tutorial for more information about I2C addressing and other technical details. + +## Available functions :id=available-functions |Function |Description | |------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |`void i2c_init(void);` |Initializes the I2C driver. This function should be called once before any transaction is initiated. | -|`uint8_t i2c_start(uint8_t address, uint16_t timeout);` |Starts an I2C transaction. Address is the 7-bit slave address without the direction bit. | -|`uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Transmit data over I2C. Address is the 7-bit slave address without the direction. Returns status of transaction. | -|`uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Receive data over I2C. Address is the 7-bit slave address without the direction. Saves number of bytes specified by `length` in `data` array. Returns status of transaction. | -|`uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_transmit` function but `regaddr` sets where in the slave the data will be written. | -|`uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_receive` function but `regaddr` sets from where in the slave the data will be read. | -|`uint8_t i2c_stop(void);` |Ends an I2C transaction. | +|`i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` |Starts an I2C transaction. Address is the 7-bit slave address without the direction bit. | +|`i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Transmit data over I2C. Address is the 7-bit slave address without the direction. Returns status of transaction. | +|`i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Receive data over I2C. Address is the 7-bit slave address without the direction. Saves number of bytes specified by `length` in `data` array. Returns status of transaction. | +|`i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_transmit` function but `regaddr` sets where in the slave the data will be written. | +|`i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_receive` function but `regaddr` sets from where in the slave the data will be read. | +|`i2c_status_t i2c_stop(void);` |Ends an I2C transaction. | -### Function Return +### Function Return :id=function-return All the above functions, except `void i2c_init(void);` return the following truth table: -|Return Value |Description | -|---------------|---------------------------------------------------| -|0 |Operation executed successfully. | -|-1 |Operation failed. | -|-2 |Operation timed out. | +|Return Constant |Value|Description | +|--------------------|-----|--------------------------------| +|`I2C_STATUS_SUCCESS`|0 |Operation executed successfully.| +|`I2C_STATUS_ERROR` |-1 |Operation failed. | +|`I2C_STATUS_TIMEOUT`|-2 |Operation timed out. | -## AVR +## AVR :id=avr -### Configuration +### Configuration :id=avr-configuration The following defines can be used to configure the I2C master driver. @@ -37,12 +50,12 @@ The following defines can be used to configure the I2C master driver. AVRs usually have set GPIO which turn into I2C pins, therefore no further configuration is required. -## ARM +## ARM :id=arm For ARM the Chibios I2C HAL driver is under the hood. This section assumes an STM32 MCU. -### Configuration +### Configuration :id=arm-configuration The configuration for ARM MCUs can be quite complex as often there are multiple I2C drivers which can be assigned to a variety of ports. @@ -77,7 +90,7 @@ The ChibiOS I2C driver configuration depends on STM32 MCU: STM32F1xx, STM32F2xx, STM32F4xx, STM32L0xx and STM32L1xx use I2Cv1; STM32F0xx, STM32F3xx, STM32F7xx and STM32L4xx use I2Cv2; -#### I2Cv1 +#### I2Cv1 :id=i2cv1 STM32 MCUs allow for different clock and duty parameters when configuring I2Cv1. These can be modified using the following parameters, using as a reference: | Variable | Default | @@ -86,7 +99,7 @@ STM32 MCUs allow for different clock and duty parameters when configuring I2Cv1. | `I2C1_CLOCK_SPEED` | `100000` | | `I2C1_DUTY_CYCLE` | `STD_DUTY_CYCLE` | -#### I2Cv2 +#### I2Cv2 :id=i2cv2 STM32 MCUs allow for different timing parameters when configuring I2Cv2. These can be modified using the following parameters, using as a reference: | Variable | Default | @@ -104,10 +117,10 @@ STM32 MCUs allow for different "alternate function" modes when configuring GPIO | `I2C1_SCL_PAL_MODE` | `4` | | `I2C1_SDA_PAL_MODE` | `4` | -#### Other +#### Other :id=other You can also overload the `void i2c_init(void)` function, which has a weak attribute. If you do this the configuration variables above will not be used. Please consult the datasheet of your MCU for the available GPIO configurations. The following is an example initialization function: -```C +```c void i2c_init(void) { setPinInput(B6); // Try releasing special pins for a short time diff --git a/docs/index.html b/docs/index.html index 9b33cd263a46..f810e6c38fd0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -13,19 +13,38 @@ - - - + + + + +
+ +