parent
7c9d1d58ee
commit
51a7fb1f1e
@ -1 +0,0 @@
|
|||||||
docs.qmk.fm
|
|
@ -1,4 +0,0 @@
|
|||||||
# Languages
|
|
||||||
|
|
||||||
* [English](/)
|
|
||||||
* [Chinese](zh/)
|
|
@ -1,32 +0,0 @@
|
|||||||
# Quantum Mechanical Keyboard Firmware
|
|
||||||
|
|
||||||
[![Current Version](https://img.shields.io/github/tag/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/tags)
|
|
||||||
[![Build Status](https://travis-ci.org/qmk/qmk_firmware.svg?branch=master)](https://travis-ci.org/qmk/qmk_firmware)
|
|
||||||
[![Discord](https://img.shields.io/discord/440868230475677696.svg)](https://discord.gg/Uq7gcHh)
|
|
||||||
[![Docs Status](https://img.shields.io/badge/docs-ready-orange.svg)](https://docs.qmk.fm)
|
|
||||||
[![GitHub contributors](https://img.shields.io/github/contributors/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/pulse/monthly)
|
|
||||||
[![GitHub forks](https://img.shields.io/github/forks/qmk/qmk_firmware.svg?style=social&label=Fork)](https://github.com/qmk/qmk_firmware/)
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
## How to Get It
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Otherwise, you can either download it directly ([zip](https://github.com/qmk/qmk_firmware/zipball/master), [tar](https://github.com/qmk/qmk_firmware/tarball/master)), or clone it via git (`git@github.com:qmk/qmk_firmware.git`), or https (`https://github.com/qmk/qmk_firmware.git`).
|
|
||||||
|
|
||||||
## How to Compile
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
make planck/rev4:default
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
make preonic:default
|
|
||||||
|
|
||||||
## How to Customize
|
|
||||||
|
|
||||||
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).
|
|
@ -1,106 +0,0 @@
|
|||||||
* [Complete Newbs Guide](newbs.md)
|
|
||||||
* [Getting Started](newbs_getting_started.md)
|
|
||||||
* [Building Your First Firmware](newbs_building_firmware.md)
|
|
||||||
* [Flashing Firmware](newbs_flashing.md)
|
|
||||||
* [Testing and Debugging](newbs_testing_debugging.md)
|
|
||||||
* [Git Best Practices](newbs_best_practices.md)
|
|
||||||
* [Learning Resources](newbs_learn_more_resources.md)
|
|
||||||
|
|
||||||
* [QMK Basics](README.md)
|
|
||||||
* [QMK Introduction](getting_started_introduction.md)
|
|
||||||
* [Contributing to QMK](contributing.md)
|
|
||||||
* [How to Use Github](getting_started_github.md)
|
|
||||||
* [Getting Help](getting_started_getting_help.md)
|
|
||||||
|
|
||||||
* [FAQ](faq.md)
|
|
||||||
* [General FAQ](faq_general.md)
|
|
||||||
* [Build/Compile QMK](faq_build.md)
|
|
||||||
* [Debugging/Troubleshooting QMK](faq_debug.md)
|
|
||||||
* [Keymap](faq_keymap.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)
|
|
||||||
|
|
||||||
* [Hardware](hardware.md)
|
|
||||||
* [AVR Processors](hardware_avr.md)
|
|
||||||
* [Drivers](hardware_drivers.md)
|
|
||||||
|
|
||||||
* Reference
|
|
||||||
* [Keyboard Guidelines](hardware_keyboard_guidelines.md)
|
|
||||||
* [Config Options](config_options.md)
|
|
||||||
* [Keycodes](keycodes.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)
|
|
||||||
|
|
||||||
* [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)
|
|
||||||
* [Command](feature_command.md)
|
|
||||||
* [Dynamic Macros](feature_dynamic_macros.md)
|
|
||||||
* [Encoders](feature_encoders.md)
|
|
||||||
* [Grave Escape](feature_grave_esc.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)
|
|
||||||
* [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 Shift](feature_space_cadet_shift.md)
|
|
||||||
* [Space Cadet Shift Enter](feature_space_cadet_shift_enter.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)
|
|
||||||
|
|
||||||
* For Makers and Modders
|
|
||||||
* [Hand Wiring Guide](hand_wire.md)
|
|
||||||
* [ISP Flashing Guide](isp_flashing_guide.md)
|
|
||||||
* [ARM Debugging Guide](arm_debugging.md)
|
|
||||||
* [I2C Driver](i2c_driver.md)
|
|
||||||
* [GPIO Controls](internals_gpio_control.md)
|
|
||||||
* [Proton C Conversion](proton_c_conversion.md)
|
|
||||||
|
|
||||||
* For a Deeper Understanding
|
|
||||||
* [How Keyboards Work](how_keyboards_work.md)
|
|
||||||
* [Understanding QMK](understanding_qmk.md)
|
|
||||||
|
|
||||||
* Other Topics
|
|
||||||
* [Using Eclipse with QMK](other_eclipse.md)
|
|
||||||
* [Using VSCode with QMK](other_vscode.md)
|
|
||||||
* [Support](support.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)
|
|
@ -1,87 +0,0 @@
|
|||||||
# ARM Debugging usign Eclipse
|
|
||||||
|
|
||||||
This page describes how to setup debugging for ARM MCUs using an SWD adapter and open-source/free tools. In this guide we will install GNU MCU Eclipse IDE for C/C++ Developers and OpenOCD together with all the necessary dependencies.
|
|
||||||
|
|
||||||
This guide is catered towards advance users and assumes you can compile an ARM compatible keyboard on your machine using the MAKE flow.
|
|
||||||
|
|
||||||
## Installing the software
|
|
||||||
|
|
||||||
The main objective here is to get the MCU Eclipse IDE correcly installed on our machine. The necesarry instructions are derived from [this](https://gnu-mcu-eclipse.github.io/install/) install guide.
|
|
||||||
|
|
||||||
### The xPack Manager
|
|
||||||
|
|
||||||
This tool is a software package manager and it is used to help us get the necesarry depencencies.
|
|
||||||
|
|
||||||
XPM runs using Node.js so grab that form [here](https://nodejs.org/en/). After installation, open a terminal and type `npm -v`. A reply with the version number means that the instalation was successful.
|
|
||||||
|
|
||||||
XPM instalation instructions can be found [here](https://www.npmjs.com/package/xpm) and are OS specific. Entering `xpm --version` to your terminal should return the software version.
|
|
||||||
|
|
||||||
### The ARM Toolchain
|
|
||||||
|
|
||||||
Using XPM it is very easy to install the ARM toolchain. Enter the command `xpm install --global @gnu-mcu-eclipse/arm-none-eabi-gcc`.
|
|
||||||
|
|
||||||
### Windows build tools
|
|
||||||
|
|
||||||
If you are using windows you need to install this!
|
|
||||||
|
|
||||||
`xpm install --global @gnu-mcu-eclipse/windows-build-tools`
|
|
||||||
|
|
||||||
### Programer/Debugger Drivers
|
|
||||||
|
|
||||||
Now its the time to install your programer's drivers. This tutorial was made using an ST-Link v2 which you can get from almost anywhere.
|
|
||||||
If you have an ST-Link the drivers can be found [here](https://www.st.com/en/development-tools/stsw-link009.html) otherwise consult the manufuturer of your tool.
|
|
||||||
|
|
||||||
### OpenOCD
|
|
||||||
|
|
||||||
This dependency allows SWD access from GDB and it is essential for debugging. Run `xpm install --global @gnu-mcu-eclipse/openocd`.
|
|
||||||
|
|
||||||
### Java
|
|
||||||
|
|
||||||
Java is needed by Eclipse so please download it from [here](https://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
|
||||||
|
|
||||||
### GNU MCU Eclipse IDE
|
|
||||||
|
|
||||||
Now its finally time to install the IDE. Use the Release page [here](https://github.com/gnu-mcu-eclipse/org.eclipse.epp.packages/releases/) to get the latest version.
|
|
||||||
|
|
||||||
## Configuring Eclipse
|
|
||||||
|
|
||||||
Open up the Eclipse IDE we just downloaded. To import our QMK directory select File -> Import -> C/C++ -> Existing code as Makefile Project. Select next and use Browse to select your QMK folder. In the tool-chain list select ARM Cross GCC and select Finish.
|
|
||||||
|
|
||||||
Now you can see the QMK folder on the left hand side. Right click it and select Properties. On the left hand side, expand MCU and select ARM Toolchain Paths. Press xPack and OK. Repeat for OpenOCD Path and if you are on windows for Build Tool Path. Select Apply and Close.
|
|
||||||
|
|
||||||
Now its time to install the necessary MCU packages. Go to Packs perspective by selecting Window -> Open Perspective -> Others -> Packs. Now select the yellow refresh symbol next to the Packs tab. This will take a long time as it is requesting the MCU definitions from various places. If some of the links fail you can probably select Ignore.
|
|
||||||
|
|
||||||
When this finishes you must find the MCU which we will be building/debugging for. In this example I will be using the STM32F3 series MCUs. On the left, select STMicroelectonics -> STM32F3 Series. On the middle window we can see the pack. Right click and select Install. Once that is done we can go back to the default perspective, Window -> Open Perspective -> Others -> C/C++.
|
|
||||||
|
|
||||||
We need to let eclipse know the device we intent to build QMK on. Right click on the QMK folder -> Properties -> C/C++ Build -> Settings. Select the Devices tab and under devices select the appropriate variant of your MCU. For my example it is STM32F303CC
|
|
||||||
|
|
||||||
While we are here let's setup the build command as well. Select C/C++ Build and then the Behavior tab. On the build command, replace `all` with your necessary make command. For example for a rev6 Planck with the default keymap this would be `planck/rev6:default`. Select Apply and Close.
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
If you have setup everything correctly pressing the hammer button should build the firmware for you and a .bin file should appear.
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
### Connecting the Debugger
|
|
||||||
|
|
||||||
ARM MCUs use the Single Wire Debug (SWD) protocol which comprises of the clock (SWCLK) signal and the data (SWDIO) signal. Connecting this two wires and ground should be enough to allow full manipulation of the MCU. Here we assume that the keyboard will be powered though USB. The RESET signal is not necessary as we can manually assert it using the reset button. For a more advance setup, the SWO signal can be used which pipes printf and scanf asynchronously to the host but for our setup we will ignore it.
|
|
||||||
|
|
||||||
NOTE: Make sure the SWCLK and SWDIO pins are not used in the matrix of your keyboard. If they are you can temporarily switch them for some other pins.
|
|
||||||
|
|
||||||
### Configuring the Debugger
|
|
||||||
|
|
||||||
Right click on your QMK folder, select Debug As -> Debug Configuration. Here double click on GDB OpenOCD Debugging. Select the debugger tab and enter the configuration necessary for your MCU. This might take some fiddling and googleing to find out. The default script for the STM32F3 is called stm32f3discovery.cfg. To let OpenOCD know, in the Config options enter `-f board/stm32f3discovery.cfg`.
|
|
||||||
|
|
||||||
NOTE: In my case this configuration script requires editing to disable the reset assertion. The locations of the scripts can be found in the actual executable field usually under the path `openocd/version/.content/scripts/board`. Here I edited `reset_config srst_only` to `reset_config none`.
|
|
||||||
|
|
||||||
Select Apply and Close.
|
|
||||||
|
|
||||||
### Running the Debugger.
|
|
||||||
|
|
||||||
Reset your keyboard.
|
|
||||||
|
|
||||||
Press the bug icon and if all goes well you should soon find yourself in the debug perspective. Here the program counter will pause at the beginning of the main function and way for you to press Play. Most of the features of all debuggers work on ARM MCUs but for exact details google is your friend!
|
|
||||||
|
|
||||||
|
|
||||||
Happy debugging!
|
|
@ -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!
|
|
@ -1,25 +0,0 @@
|
|||||||
# Atmel AVR
|
|
||||||
|
|
||||||
QMK should run on any Atmel AVR processor with enough Flash. It has been tested on the following:
|
|
||||||
|
|
||||||
* ATmega32U4 ([PJRC Teensy 2.0](http://www.pjrc.com/teensy/))
|
|
||||||
* AT90USB1286 ([PJRC Teensy++ 2.0](http://www.pjrc.com/teensy/))
|
|
||||||
* AT90USB1287 ([Atmel USBKEY](http://www.atmel.com/tools/AT90USBKEY.aspx))
|
|
||||||
* ATmega168P with using [V-USB](http://www.obdev.at/products/vusb/index.html)
|
|
||||||
* ATmega328P with using [V-USB](http://www.obdev.at/products/vusb/index.html)
|
|
||||||
* ATmega32U2
|
|
||||||
* AT90USB1286, 646, 647 should work
|
|
||||||
* AT90USB162 testing...
|
|
||||||
|
|
||||||
NOTE: To enable full features of firmware you'll need 32KB flash size.
|
|
||||||
|
|
||||||
Please add any tested microcontrollers to this list.
|
|
||||||
|
|
||||||
# ARM
|
|
||||||
|
|
||||||
You can also use any ARM processor that [ChibiOS](http://www.chibios.org) supports. The following processors have been tested:
|
|
||||||
|
|
||||||
* [Kinetis MKL26Z64](http://www.nxp.com/products/microcontrollers-and-processors/arm-processors/kinetis-cortex-m-mcus/l-series-ultra-low-power-m0-plus/kinetis-kl2x-48-mhz-usb-ultra-low-power-microcontrollers-mcus-based-on-arm-cortex-m0-plus-core:KL2x)
|
|
||||||
* [Kinetis MK20DX128](http://www.nxp.com/assets/documents/data/en/data-sheets/K20P64M50SF0.pdf)
|
|
||||||
* [Kinetis MK20DX128](http://www.nxp.com/assets/documents/data/en/data-sheets/K20P64M50SF0.pdf)
|
|
||||||
* [Kinetis MK20DX256](http://www.nxp.com/products/microcontrollers-and-processors/arm-processors/kinetis-cortex-m-mcus/k-series-performance-m4/k2x-usb/kinetis-k20-72-mhz-full-speed-usb-mixed-signal-integration-microcontrollers-mcus-based-on-arm-cortex-m4-core:K20_72)
|
|
@ -1,355 +0,0 @@
|
|||||||
# Configuring QMK
|
|
||||||
|
|
||||||
QMK is nearly infinitely configurable. Wherever possible we err on the side of allowing users to customize their keyboard, even at the expense of code size. That level of flexibility makes for a daunting configuration experience, however.
|
|
||||||
|
|
||||||
There are two main types of configuration files in QMK- `config.h` and `rules.mk`. These files exist at various levels in QMK and all files of the same type are combined to build the final configuration. The levels, from lowest priority to highest priority, are:
|
|
||||||
|
|
||||||
* QMK Default
|
|
||||||
* Keyboard
|
|
||||||
* Folders (Up to 5 levels deep)
|
|
||||||
* Keymap
|
|
||||||
|
|
||||||
## QMK Default
|
|
||||||
|
|
||||||
Every available setting in QMK has a default. If that setting is not set at the Keyboard, Folder, or Keymap level this is the setting that will be used.
|
|
||||||
|
|
||||||
## Keyboard
|
|
||||||
|
|
||||||
This level contains config options that should apply to the whole keyboard. Some settings won't change in revisions, or most keymaps. Other settings are merely defaults for this keyboard and can be overridden by folders and/or keymaps.
|
|
||||||
|
|
||||||
## Folders
|
|
||||||
|
|
||||||
Some keyboards have folders and sub-folders to allow for different hardware configurations. Most keyboards only go 1 folder deep, but QMK supports structures up to 5 folders deep. Each folder can have its own `config.h` and `rules.mk` files that are incorporated into the final configuration.
|
|
||||||
|
|
||||||
## Keymap
|
|
||||||
|
|
||||||
This level contains all of the options for that particular keymap. If you wish to override a previous declaration, you can use `#undef <variable>` to undefine it, where you can then redefine it without an error.
|
|
||||||
|
|
||||||
# The `config.h` File
|
|
||||||
|
|
||||||
This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files, or anything besides this:
|
|
||||||
|
|
||||||
#include "config_common.h"
|
|
||||||
|
|
||||||
|
|
||||||
## Hardware Options
|
|
||||||
* `#define VENDOR_ID 0x1234`
|
|
||||||
* defines your VID, and for most DIY projects, can be whatever you want
|
|
||||||
* `#define PRODUCT_ID 0x5678`
|
|
||||||
* defines your PID, and for most DIY projects, can be whatever you want
|
|
||||||
* `#define DEVICE_VER 0`
|
|
||||||
* defines the device version (often used for revisions)
|
|
||||||
* `#define MANUFACTURER Me`
|
|
||||||
* generally who/whatever brand produced the board
|
|
||||||
* `#define PRODUCT Board`
|
|
||||||
* the name of the keyboard
|
|
||||||
* `#define DESCRIPTION a keyboard`
|
|
||||||
* a short description of what the keyboard is
|
|
||||||
* `#define MATRIX_ROWS 5`
|
|
||||||
* the number of rows in your keyboard's matrix
|
|
||||||
* `#define MATRIX_COLS 15`
|
|
||||||
* the number of columns in your keyboard's matrix
|
|
||||||
* `#define MATRIX_ROW_PINS { D0, D5, B5, B6 }`
|
|
||||||
* pins of the rows, from top to bottom
|
|
||||||
* `#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }`
|
|
||||||
* pins of the columns, from left to right
|
|
||||||
* `#define UNUSED_PINS { D1, D2, D3, B1, B2, B3 }`
|
|
||||||
* pins unused by the keyboard for reference
|
|
||||||
* `#define MATRIX_HAS_GHOST`
|
|
||||||
* define is matrix has ghost (unlikely)
|
|
||||||
* `#define DIODE_DIRECTION COL2ROW`
|
|
||||||
* COL2ROW or ROW2COL - how your matrix is configured. COL2ROW means the black mark on your diode is facing to the rows, and between the switch and the rows.
|
|
||||||
* `#define AUDIO_VOICES`
|
|
||||||
* turns on the alternate audio voices (to cycle through)
|
|
||||||
* `#define C4_AUDIO`
|
|
||||||
* enables audio on pin C4
|
|
||||||
* `#define C5_AUDIO`
|
|
||||||
* enables audio on pin C5
|
|
||||||
* `#define C6_AUDIO`
|
|
||||||
* enables audio on pin C6
|
|
||||||
* `#define B5_AUDIO`
|
|
||||||
* enables audio on pin B5 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
|
|
||||||
* `#define B6_AUDIO`
|
|
||||||
* enables audio on pin B6 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
|
|
||||||
* `#define B7_AUDIO`
|
|
||||||
* enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
|
|
||||||
* `#define BACKLIGHT_PIN B7`
|
|
||||||
* pin of the backlight - B5, B6, B7 use PWM, others use softPWM
|
|
||||||
* `#define BACKLIGHT_LEVELS 3`
|
|
||||||
* number of levels your backlight will have (maximum 15 excluding off)
|
|
||||||
* `#define BACKLIGHT_BREATHING`
|
|
||||||
* enables backlight breathing (only works with backlight pins B5, B6 and B7)
|
|
||||||
* `#define BREATHING_PERIOD 6`
|
|
||||||
* the length of one backlight "breath" in seconds
|
|
||||||
* `#define DEBOUNCING_DELAY 5`
|
|
||||||
* the delay when reading the value of the pin (5 is default)
|
|
||||||
* `#define LOCKING_SUPPORT_ENABLE`
|
|
||||||
* mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap
|
|
||||||
* `#define LOCKING_RESYNC_ENABLE`
|
|
||||||
* tries to keep switch state consistent with keyboard LED state
|
|
||||||
* `#define IS_COMMAND() (get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))`
|
|
||||||
* key combination that allows the use of magic commands (useful for debugging)
|
|
||||||
* `#define USB_MAX_POWER_CONSUMPTION`
|
|
||||||
* sets the maximum power (in mA) over USB for the device (default: 500)
|
|
||||||
* `#define SCL_CLOCK 100000L`
|
|
||||||
* sets the SCL_CLOCK speed for split keyboards. The default is `100000L` but some boards can be set to `400000L`.
|
|
||||||
|
|
||||||
## Features That Can Be Disabled
|
|
||||||
|
|
||||||
If you define these options you will disable the associated feature, which can save on code size.
|
|
||||||
|
|
||||||
* `#define NO_DEBUG`
|
|
||||||
* disable debugging
|
|
||||||
* `#define NO_PRINT`
|
|
||||||
* disable printing/debugging using hid_listen
|
|
||||||
* `#define NO_ACTION_LAYER`
|
|
||||||
* disable layers
|
|
||||||
* `#define NO_ACTION_TAPPING`
|
|
||||||
* disable tap dance and other tapping features
|
|
||||||
* `#define NO_ACTION_ONESHOT`
|
|
||||||
* disable one-shot modifiers
|
|
||||||
* `#define NO_ACTION_MACRO`
|
|
||||||
* disable old style macro handling: MACRO() & action_get_macro
|
|
||||||
* `#define NO_ACTION_FUNCTION`
|
|
||||||
* disable calling of action_function() from the fn_actions array (deprecated)
|
|
||||||
|
|
||||||
## Features That Can Be Enabled
|
|
||||||
|
|
||||||
If you define these options you will enable the associated feature, which may increase your code size.
|
|
||||||
|
|
||||||
* `#define FORCE_NKRO`
|
|
||||||
* NKRO by default requires to be turned on, this forces it on during keyboard startup regardless of EEPROM setting. NKRO can still be turned off but will be turned on again if the keyboard reboots.
|
|
||||||
* `#define STRICT_LAYER_RELEASE`
|
|
||||||
* force a key release to be evaluated using the current layer stack instead of remembering which layer it came from (used for advanced cases)
|
|
||||||
|
|
||||||
## Behaviors That Can Be Configured
|
|
||||||
|
|
||||||
* `#define TAPPING_TERM 200`
|
|
||||||
* how long before a tap becomes a hold, if set above 500, a key tapped during the tapping term will turn it into a hold too
|
|
||||||
* `#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
|
|
||||||
* `#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
|
|
||||||
* `#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
|
|
||||||
* `#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)
|
|
||||||
* Breaks any Tap Toggle functionality (`TT` or the One Shot Tap Toggle)
|
|
||||||
* `#define LEADER_TIMEOUT 300`
|
|
||||||
* how long before the leader key times out
|
|
||||||
* If you're having issues finishing the sequence before it times out, you may need to increase the timeout setting. Or you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped.
|
|
||||||
* `#define LEADER_PER_KEY_TIMING`
|
|
||||||
* sets the timer for leader key chords to run on each key press rather than overall
|
|
||||||
* `#define LEADER_KEY_STRICT_KEY_PROCESSING`
|
|
||||||
* Disables keycode filtering for Mod-Tap and Layer-Tap keycodes. Eg, if you enable this, you would need to specify `MT(MOD_CTL, KC_A)` if you want to use `KC_A`.
|
|
||||||
* `#define ONESHOT_TIMEOUT 300`
|
|
||||||
* how long before oneshot times out
|
|
||||||
* `#define ONESHOT_TAP_TOGGLE 2`
|
|
||||||
* how many taps before oneshot toggle is triggered
|
|
||||||
* `#define QMK_KEYS_PER_SCAN 4`
|
|
||||||
* Allows sending more than one key per scan. By default, only one key event gets
|
|
||||||
sent via `process_record()` per scan. This has little impact on most typing, but
|
|
||||||
if you're doing a lot of chords, or your scan rate is slow to begin with, you can
|
|
||||||
have some delay in processing key events. Each press and release is a separate
|
|
||||||
event. For a keyboard with 1ms or so scan times, even a very fast typist isn't
|
|
||||||
going to produce the 500 keystrokes a second needed to actually get more than a
|
|
||||||
few ms of delay from this. But if you're doing chording on something with 3-4ms
|
|
||||||
scan times? You probably want this.
|
|
||||||
* `#define COMBO_COUNT 2`
|
|
||||||
* Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature.
|
|
||||||
* `#define COMBO_TERM 200`
|
|
||||||
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
|
|
||||||
* `#define TAP_CODE_DELAY 100`
|
|
||||||
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds.
|
|
||||||
|
|
||||||
## RGB Light Configuration
|
|
||||||
|
|
||||||
* `#define RGB_DI_PIN D7`
|
|
||||||
* pin the DI on the WS2812 is hooked-up to
|
|
||||||
* `#define RGBLIGHT_ANIMATIONS`
|
|
||||||
* run RGB animations
|
|
||||||
* `#define RGBLED_NUM 12`
|
|
||||||
* number of LEDs
|
|
||||||
* `#define RGBLED_SPLIT { 6, 6 }`
|
|
||||||
* number of LEDs connected that are directly wired to `RGB_DI_PIN` on each half of a split keyboard
|
|
||||||
* First value indicates number of LEDs for left half, second value is for the right half
|
|
||||||
* Needed if both halves of the board have RGB LEDs wired directly to the RGB output pin on the controllers instead of passing the output of the left half to the input of the right half
|
|
||||||
* `#define RGBLIGHT_HUE_STEP 12`
|
|
||||||
* units to step when in/decreasing hue
|
|
||||||
* `#define RGBLIGHT_SAT_STEP 25`
|
|
||||||
* units to step when in/decreasing saturation
|
|
||||||
* `#define RGBLIGHT_VAL_STEP 12`
|
|
||||||
* units to step when in/decreasing value (brightness)
|
|
||||||
* `#define RGBW_BB_TWI`
|
|
||||||
* bit-bangs TWI to EZ RGBW LEDs (only required for Ergodox EZ)
|
|
||||||
|
|
||||||
## Mouse Key Options
|
|
||||||
|
|
||||||
* `#define MOUSEKEY_INTERVAL 20`
|
|
||||||
* `#define MOUSEKEY_DELAY 0`
|
|
||||||
* `#define MOUSEKEY_TIME_TO_MAX 60`
|
|
||||||
* `#define MOUSEKEY_MAX_SPEED 7`
|
|
||||||
* `#define MOUSEKEY_WHEEL_DELAY 0`
|
|
||||||
|
|
||||||
## Split Keyboard Options
|
|
||||||
|
|
||||||
Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk
|
|
||||||
|
|
||||||
* `SPLIT_TRANSPORT = custom`
|
|
||||||
* Allows replacing the standard split communication routines with a custom one. ARM based split keyboards must use this at present.
|
|
||||||
|
|
||||||
### Setting Handedness
|
|
||||||
|
|
||||||
One thing to remember, the side that the USB port is plugged into is always the master half. The side not plugged into USB is the slave.
|
|
||||||
|
|
||||||
There are a few different ways to set handedness for split keyboards (listed in order of precedence):
|
|
||||||
|
|
||||||
1. Set `SPLIT_HAND_PIN`: Reads a pin to determine handedness. If pin is high, it's the left side, if low, the half is determined to be the right side
|
|
||||||
2. Set `EE_HANDS` and flash `eeprom-lefthand.eep`/`eeprom-righthand.eep` to each half
|
|
||||||
* For boards with DFU bootloader you can use `:dfu-split-left`/`:dfu-split-right` to flash these EEPROM files
|
|
||||||
* For boards with Caterina bootloader (like stock Pro Micros), use `:avrdude-split-left`/`:avrdude-split-right`
|
|
||||||
3. Set `MASTER_RIGHT`: Half that is plugged into the USB port is determined to be the master and right half (inverse of the default)
|
|
||||||
4. Default: The side that is plugged into the USB port is the master half and is assumed to be the left half. The slave side is the right half
|
|
||||||
|
|
||||||
#### Defines for handedness
|
|
||||||
|
|
||||||
* `#define SPLIT_HAND_PIN B7`
|
|
||||||
* For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
|
|
||||||
|
|
||||||
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` is not defined)
|
|
||||||
* Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves.
|
|
||||||
|
|
||||||
* `#define MASTER_RIGHT`
|
|
||||||
* Master half is defined to be the right half.
|
|
||||||
|
|
||||||
### Other Options
|
|
||||||
|
|
||||||
* `#define USE_I2C`
|
|
||||||
* For using I2C instead of Serial (defaults to serial)
|
|
||||||
|
|
||||||
* `#define SOFT_SERIAL_PIN D0`
|
|
||||||
* When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`.
|
|
||||||
|
|
||||||
* `#define MATRIX_ROW_PINS_RIGHT { <row pins> }`
|
|
||||||
* `#define MATRIX_COL_PINS_RIGHT { <col pins> }`
|
|
||||||
* If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns.
|
|
||||||
|
|
||||||
* `#define RGBLED_SPLIT { 6, 6 }`
|
|
||||||
* See [RGB Light Configuration](#rgb-light-configuration)
|
|
||||||
|
|
||||||
* `#define SELECT_SOFT_SERIAL_SPEED <speed>` (default speed is 1)
|
|
||||||
* Sets the protocol speed when using serial communication
|
|
||||||
* Speeds:
|
|
||||||
* 0: about 189kbps (Experimental only)
|
|
||||||
* 1: about 137kbps (default)
|
|
||||||
* 2: about 75kbps
|
|
||||||
* 3: about 39kbps
|
|
||||||
* 4: about 26kbps
|
|
||||||
* 5: about 20kbps
|
|
||||||
|
|
||||||
# The `rules.mk` File
|
|
||||||
|
|
||||||
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
|
|
||||||
|
|
||||||
## Build Options
|
|
||||||
|
|
||||||
* `DEFAULT_FOLDER`
|
|
||||||
* Used to specify a default folder when a keyboard has more than one sub-folder.
|
|
||||||
* `FIRMWARE_FORMAT`
|
|
||||||
* Defines which format (bin, hex) is copied to the root `qmk_firmware` folder after building.
|
|
||||||
* `SRC`
|
|
||||||
* Used to add files to the compilation/linking list.
|
|
||||||
* `LAYOUTS`
|
|
||||||
* A list of [layouts](feature_layouts.md) this keyboard supports.
|
|
||||||
|
|
||||||
## AVR MCU Options
|
|
||||||
* `MCU = atmega32u4`
|
|
||||||
* `F_CPU = 16000000`
|
|
||||||
* `ARCH = AVR8`
|
|
||||||
* `F_USB = $(F_CPU)`
|
|
||||||
* `OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT`
|
|
||||||
* `BOOTLOADER = atmel-dfu` with the following options:
|
|
||||||
* `atmel-dfu`
|
|
||||||
* `lufa-dfu`
|
|
||||||
* `qmk-dfu`
|
|
||||||
* `halfkay`
|
|
||||||
* `caterina`
|
|
||||||
* `bootloadHID`
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
* `BOOTMAGIC_ENABLE`
|
|
||||||
* Virtual DIP switch configuration(+1000)
|
|
||||||
* `MOUSEKEY_ENABLE`
|
|
||||||
* Mouse keys(+4700)
|
|
||||||
* `EXTRAKEY_ENABLE`
|
|
||||||
* Audio control and System control(+450)
|
|
||||||
* `CONSOLE_ENABLE`
|
|
||||||
* Console for debug(+400)
|
|
||||||
* `COMMAND_ENABLE`
|
|
||||||
* Commands for debug and configuration
|
|
||||||
* `COMBO_ENABLE`
|
|
||||||
* Key combo feature
|
|
||||||
* `NKRO_ENABLE`
|
|
||||||
* USB N-Key Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
|
||||||
* `AUDIO_ENABLE`
|
|
||||||
* Enable the audio subsystem.
|
|
||||||
* `RGBLIGHT_ENABLE`
|
|
||||||
* Enable keyboard underlight functionality
|
|
||||||
* `LEADER_ENABLE`
|
|
||||||
* Enable leader key chording
|
|
||||||
* `MIDI_ENABLE`
|
|
||||||
* MIDI controls
|
|
||||||
* `UNICODE_ENABLE`
|
|
||||||
* Unicode
|
|
||||||
* `BLUETOOTH_ENABLE`
|
|
||||||
* Legacy option to Enable Bluetooth with the Adafruit EZ-Key HID. See BLUETOOTH
|
|
||||||
* `BLUETOOTH`
|
|
||||||
* Current options are AdafruitEzKey, AdafruitBLE, RN42
|
|
||||||
* `SPLIT_KEYBOARD`
|
|
||||||
* Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
|
|
||||||
* `CUSTOM_MATRIX`
|
|
||||||
* Allows replacing the standard matrix scanning routine with a custom one.
|
|
||||||
* `DEBOUNCE_TYPE`
|
|
||||||
* Allows replacing the standard key debouncing routine with an alternative or custom one.
|
|
||||||
* `WAIT_FOR_USB`
|
|
||||||
* Forces the keyboard to wait for a USB connection to be established before it starts up
|
|
||||||
* `NO_USB_STARTUP_CHECK`
|
|
||||||
* Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master.
|
|
||||||
|
|
||||||
## USB Endpoint Limitations
|
|
||||||
|
|
||||||
In order to provide services over USB, QMK has to use USB endpoints.
|
|
||||||
These are a finite resource: each microcontroller has only a certain number.
|
|
||||||
This limits what features can be enabled together.
|
|
||||||
If the available endpoints are exceeded, a build error is thrown.
|
|
||||||
|
|
||||||
The following features can require separate endpoints:
|
|
||||||
|
|
||||||
* `MOUSEKEY_ENABLE`
|
|
||||||
* `EXTRAKEY_ENABLE`
|
|
||||||
* `CONSOLE_ENABLE`
|
|
||||||
* `NKRO_ENABLE`
|
|
||||||
* `MIDI_ENABLE`
|
|
||||||
* `RAW_ENABLE`
|
|
||||||
* `VIRTSER_ENABLE`
|
|
||||||
|
|
||||||
In order to improve utilisation of the endpoints, the HID features can be combined to use a single endpoint.
|
|
||||||
By default, `MOUSEKEY`, `EXTRAKEY`, and `NKRO` are combined into a single endpoint.
|
|
||||||
|
|
||||||
The base keyboard functionality can also be combined into the endpoint,
|
|
||||||
by setting `KEYBOARD_SHARED_EP = yes`.
|
|
||||||
This frees up one more endpoint,
|
|
||||||
but it can prevent the keyboard working in some BIOSes,
|
|
||||||
as they do not implement Boot Keyboard protocol switching.
|
|
||||||
|
|
||||||
Combining the mouse also breaks Boot Mouse compatibility.
|
|
||||||
The mouse can be uncombined by setting `MOUSE_SHARED_EP = no` if this functionality is required.
|
|
@ -1,198 +0,0 @@
|
|||||||
# How to Contribute
|
|
||||||
|
|
||||||
👍🎉 First off, thanks for taking the time to read this and contribute! 🎉👍
|
|
||||||
|
|
||||||
Third-party contributions help us grow and improve QMK. We want to make the pull request and contribution process useful and easy for both contributors and maintainers. To this end we've put together some guidelines for contributors to help your pull request be accepted without major changes.
|
|
||||||
|
|
||||||
* [Project Overview](#project-overview)
|
|
||||||
* [Coding Conventions](#coding-conventions)
|
|
||||||
* [General Guidelines](#general-guidelines)
|
|
||||||
* [What does the Code of Conduct mean for me?](#what-does-the-code-of-conduct-mean-for-me)
|
|
||||||
|
|
||||||
## I Don't Want to Read This Whole Thing! I Just Have a Question!
|
|
||||||
|
|
||||||
If you'd like to ask questions about QMK you can do so on the [OLKB Subreddit](https://reddit.com/r/olkb) or on [Discord](https://discord.gg/Uq7gcHh).
|
|
||||||
|
|
||||||
Please keep these things in mind:
|
|
||||||
|
|
||||||
* It may take several hours for someone to respond to your question. Please be patient!
|
|
||||||
* Everyone involved with QMK is donating their time and energy. We don't get paid to work on or answer questions about QMK.
|
|
||||||
* Try to ask your question so it's as easy to answer as possible. If you're not sure how to do that these are some good guides:
|
|
||||||
* https://opensource.com/life/16/10/how-ask-technical-questions
|
|
||||||
* http://www.catb.org/esr/faqs/smart-questions.html
|
|
||||||
|
|
||||||
# Project Overview
|
|
||||||
|
|
||||||
QMK is largely written in C, with specific features and parts written in C++. It targets embedded processors found in keyboards, particularly AVR ([LUFA](http://www.fourwalledcubicle.com/LUFA.php)) and ARM ([ChibiOS](http://www.chibios.com)). If you are already well versed in Arduino programming you'll find a lot of the concepts and limitations familiar. Prior experience with Arduino is not required to successfully contribute to QMK.
|
|
||||||
|
|
||||||
<!-- FIXME: We should include a list of resources for learning C here. -->
|
|
||||||
|
|
||||||
# Where Can I Go for Help?
|
|
||||||
|
|
||||||
If you need help you can [open an issue](https://github.com/qmk/qmk_firmware/issues) or [chat on Discord](https://discord.gg/Uq7gcHh).
|
|
||||||
|
|
||||||
# How Do I Make a Contribution?
|
|
||||||
|
|
||||||
Never made an open source contribution before? Wondering how contributions work in QMK? Here's a quick rundown!
|
|
||||||
|
|
||||||
0. Sign up for a [GitHub](https://github.com) account.
|
|
||||||
1. Put together a keymap to contribute, [find an issue](https://github.com/qmk/qmk_firmware/issues) you are interested in addressing, or [a feature](https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature) you would like to add.
|
|
||||||
2. Fork the repository associated with the issue to your GitHub account. This means that you will have a copy of the repository under `your-GitHub-username/qmk_firmware`.
|
|
||||||
3. Clone the repository to your local machine using `git clone https://github.com/github-username/repository-name.git`.
|
|
||||||
4. If you're working on a new feature consider opening an issue to talk with us about the work you're about to undertake.
|
|
||||||
5. Create a new branch for your fix using `git checkout -b branch-name-here`.
|
|
||||||
6. Make the appropriate changes for the issue you are trying to address or the feature that you want to add.
|
|
||||||
7. Use `git add insert-paths-of-changed-files-here` to add the file contents of the changed files to the "snapshot" git uses to manage the state of the project, also known as the index.
|
|
||||||
8. Use `git commit -m "Insert a short message of the changes made here"` to store the contents of the index with a descriptive message.
|
|
||||||
9. Push the changes to your repository on GitHub using `git push origin branch-name-here`.
|
|
||||||
10. Submit a pull request to [QMK Firmware](https://github.com/qmk/qmk_firmware/pull/new/master).
|
|
||||||
11. Title the pull request with a short description of the changes made and the issue or bug number associated with your change. For example, you can title an issue like so "Added more log outputting to resolve #4352".
|
|
||||||
12. In the description of the pull request explain the changes that you made, any issues you think exist with the pull request you made, and any questions you have for the maintainer. It's OK if your pull request is not perfect (no pull request is), the reviewer will be able to help you fix any problems and improve it!
|
|
||||||
13. Wait for the pull request to be reviewed by a maintainer.
|
|
||||||
14. Make changes to the pull request if the reviewing maintainer recommends them.
|
|
||||||
15. Celebrate your success after your pull request is merged!
|
|
||||||
|
|
||||||
# Coding Conventions
|
|
||||||
|
|
||||||
Most of our style is pretty easy to pick up on, but right now it's not entirely consistent. You should match the style of the code surrounding your change, but if that code is inconsistent or unclear use the following guidelines:
|
|
||||||
|
|
||||||
* We indent using two spaces (soft tabs)
|
|
||||||
* We use a modified One True Brace Style
|
|
||||||
* Opening Brace: At the end of the same line as the statement that opens the block
|
|
||||||
* Closing Brace: Lined up with the first character of the statement that opens the block
|
|
||||||
* Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
|
|
||||||
* Optional Braces: Always include optional braces.
|
|
||||||
* Good: if (condition) { return false; }
|
|
||||||
* Bad: if (condition) return false;
|
|
||||||
* We encourage use of C style comments: `/* */`
|
|
||||||
* Think of them as a story describing the feature
|
|
||||||
* Use them liberally to explain why particular decisions were made.
|
|
||||||
* Do not write obvious comments
|
|
||||||
* If you not sure if a comment is obvious, go ahead and include it.
|
|
||||||
* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
|
|
||||||
* We use `#pragma once` at the start of header files rather than old-style include guards (`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)
|
|
||||||
|
|
||||||
Here is an example for easy reference:
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Enums for foo */
|
|
||||||
enum foo_state {
|
|
||||||
FOO_BAR,
|
|
||||||
FOO_BAZ,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Returns a value */
|
|
||||||
int foo(void) {
|
|
||||||
if (some_condition) {
|
|
||||||
return FOO_BAR;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# Auto-formatting with clang-format
|
|
||||||
|
|
||||||
[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) is part of LLVM and can automatically format your code for you, because ain't nobody got time to do it manually. We supply a configuration file for it that applies most of the coding conventions listed above. It will only change whitespace and newlines, so you will still have to remember to include optional braces yourself.
|
|
||||||
|
|
||||||
Use the [full LLVM installer](http://llvm.org/builds/) to get clang-format on Windows, or use `sudo apt install clang-format` on Ubuntu.
|
|
||||||
|
|
||||||
If you run it from the command-line, pass `-style=file` as an option and it will automatically find the .clang-format configuration file in the QMK root directory.
|
|
||||||
|
|
||||||
If you use VSCode, the standard C/C++ plugin supports clang-format, alternatively there is a [separate extension](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) for it.
|
|
||||||
|
|
||||||
Some things (like LAYOUT macros) are destroyed by clang-format, so either don't run it on those files, or wrap the sensitive code in `// clang-format off` and `// clang-format on`.
|
|
||||||
|
|
||||||
# General Guidelines
|
|
||||||
|
|
||||||
We have a few different types of changes in QMK, each requiring a different level of rigor. We'd like you to keep the following guidelines in mind no matter what type of change you're making.
|
|
||||||
|
|
||||||
* Separate PR's into logical units. For example, do not submit one PR covering two separate features, instead submit a separate PR for each feature.
|
|
||||||
* Check for unnecessary whitespace with `git diff --check` before committing.
|
|
||||||
* Make sure your code change actually compiles.
|
|
||||||
* Keymaps: Make sure that `make keyboard:your_new_keymap` does not return an error
|
|
||||||
* Keyboards: Make sure that `make keyboard:all` does not return any errors
|
|
||||||
* Core: Make sure that `make all` does not return any errors.
|
|
||||||
* Make sure commit messages are understandable on their own. You should put a short description (no more than 70 characters) on the first line, the second line should be empty, and on the 3rd and later lines you should describe your commit in detail, if required. Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
Adjust the fronzlebop for the kerpleplork
|
|
||||||
|
|
||||||
The kerpleplork was intermittently failing with error code 23. The root cause was the fronzlebop setting, which causes the kerpleplork to activate every N iterations.
|
|
||||||
|
|
||||||
Limited experimentation on the devices I have available shows that 7 is high enough to avoid confusing the kerpleplork, but I'd like to get some feedback from people with ARM devices to be sure.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
Documentation is one of the easiest ways to get started contributing to QMK. Finding places where the documentation is wrong or incomplete and fixing those is easy! We also very badly need someone to edit our documentation, so if you have editing skills but aren't sure where or how to jump in please [reach out for help](#where-can-i-go-for-help)!
|
|
||||||
|
|
||||||
You'll find all our documentation in the `qmk_firmware/docs` directory, or if you'd rather use a web based workflow you can click "Suggest An Edit" at the top of each page on http://docs.qmk.fm/.
|
|
||||||
|
|
||||||
When providing code examples in your documentation, try to observe naming conventions used elsewhere in the docs. For example, standardizing enums as `my_layers` or `my_keycodes` for consistency:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum my_layers {
|
|
||||||
_FIRST_LAYER,
|
|
||||||
_SECOND_LAYER
|
|
||||||
};
|
|
||||||
|
|
||||||
enum my_keycodes {
|
|
||||||
FIRST_LAYER = SAFE_RANGE,
|
|
||||||
SECOND_LAYER
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Keymaps
|
|
||||||
|
|
||||||
Most first-time QMK contributors start with their personal keymaps. We try to keep keymap standards pretty casual (keymaps, after all, reflect the personality of their creators) but we do ask that you follow these guidelines to make it easier for others to discover and learn from your keymap.
|
|
||||||
|
|
||||||
* Write a `readme.md` using [the template](documentation_templates.md).
|
|
||||||
* All Keymap PR's are squashed, so if you care about how your commits are squashed you should do it yourself
|
|
||||||
* Do not lump features in with keymap PR's. Submit the feature first and then a second PR for the keymap.
|
|
||||||
* Do not include `Makefile`s in your keymap folder (they're no longer used)
|
|
||||||
* Update copyrights in file headers (look for `%YOUR_NAME%`)
|
|
||||||
|
|
||||||
## Keyboards
|
|
||||||
|
|
||||||
Keyboards are the raison d'être for QMK. Some keyboards are community maintained, while others are maintained by the people responsible for making a particular keyboard. The `readme.md` should tell you who maintains a particular keyboard. If you have questions relating to a particular keyboard you can [Open An Issue](https://github.com/qmk/qmk_firmware/issues) and tag the maintainer in your question.
|
|
||||||
|
|
||||||
We also ask that you follow these guidelines:
|
|
||||||
|
|
||||||
* Write a `readme.md` using [the template](documentation_templates.md).
|
|
||||||
* Keep the number of commits reasonable or we will squash your PR
|
|
||||||
* Do not lump core features in with new keyboards. Submit the feature first and then submit a separate PR for the keyboard.
|
|
||||||
* Name `.c`/`.h` file after the immediate parent folder, eg `/keyboards/<kb1>/<kb2>/<kb2>.[ch]`
|
|
||||||
* Do not include `Makefile`s in your keyboard folder (they're no longer used)
|
|
||||||
* Update copyrights in file headers (look for `%YOUR_NAME%`)
|
|
||||||
|
|
||||||
## Quantum/TMK Core
|
|
||||||
|
|
||||||
Before you put a lot of work into building your new feature you should make sure you are implementing it in the best way. You can get a basic understanding of QMK by reading [Understanding QMK](understanding_qmk.md), which will take you on a tour of the QMK program flow. From here you should talk to us to get a sense of the best way to implement your idea. There are two main ways to do this:
|
|
||||||
|
|
||||||
* [Chat on Discord](https://discord.gg/Uq7gcHh)
|
|
||||||
* [Open an Issue](https://github.com/qmk/qmk_firmware/issues/new)
|
|
||||||
|
|
||||||
Feature and Bug Fix PR's affect all keyboards. We are also in the process of restructuring QMK. For this reason it is especially important for significant changes to be discussed before implementation has happened. If you open a PR without talking to us first please be prepared to do some significant rework if your choices do not mesh well with our planned direction.
|
|
||||||
|
|
||||||
Here are some things to keep in mind when working on your feature or bug fix.
|
|
||||||
|
|
||||||
* **Disabled by default** - memory is a pretty limited on most chips QMK supports, and it's important that current keymaps aren't broken, so please allow your feature to be turned **on**, rather than being turned off. If you think it should be on by default, or reduces the size of the code, please talk with us about it.
|
|
||||||
* **Compile locally before submitting** - hopefully this one is obvious, but things need to compile! Our Travis system will catch any issues, but it's generally faster for you to compile a few keyboards locally instead of waiting for the results to come back.
|
|
||||||
* **Consider revisions and different chip-bases** - there are several keyboards that have revisions that allow for slightly different configurations, and even different chip-bases. Try to make a feature supported in ARM and AVR, or automatically disabled on platforms it doesn't work on.
|
|
||||||
* **Explain your feature** - Document it in `docs/`, either as a new file or as part of an existing file. If you don't document it other people won't be able to benefit from your hard work.
|
|
||||||
|
|
||||||
We also ask that you follow these guidelines:
|
|
||||||
|
|
||||||
* Keep the number of commits reasonable or we will squash your PR
|
|
||||||
* Do not lump keyboards or keymaps in with core changes. Submit your core changes first.
|
|
||||||
* Write [Unit Tests](unit_testing.md) for your feature
|
|
||||||
* Follow the style of the file you are editing. If the style is unclear or there are mixed styles you should conform to the [coding conventions](#coding-conventions) above.
|
|
||||||
|
|
||||||
## Refactoring
|
|
||||||
|
|
||||||
To maintain a clear vision of how things are laid out in QMK we try to plan out refactors in-depth and have a collaborator make the changes. If you have an idea for refactoring, or suggestions, [open an issue](https://github.com/qmk/qmk_firmware/issues), we'd love to talk about how QMK can be improved.
|
|
||||||
|
|
||||||
# What Does the Code of Conduct Mean for Me?
|
|
||||||
|
|
||||||
Our [Code of Conduct](https://github.com/qmk/qmk_firmware/blob/master/CODE_OF_CONDUCT.md) means that you are responsible for treating everyone on the project with respect and courtesy regardless of their identity. If you are the victim of any inappropriate behavior or comments as described in our Code of Conduct, we are here for you and will do the best to ensure that the abuser is reprimanded appropriately, per our code.
|
|
@ -1,467 +0,0 @@
|
|||||||
# How to Customize Your Keyboard's Behavior
|
|
||||||
|
|
||||||
For a lot of people a custom keyboard is about more than sending button presses to your computer. You want to be able to do things that are more complex than simple button presses and macros. QMK has hooks that allow you to inject code, override functionality, and otherwise customize how your keyboard behaves in different situations.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
We have structured QMK as a hierarchy:
|
|
||||||
|
|
||||||
* Core (`_quantum`)
|
|
||||||
* Keyboard/Revision (`_kb`)
|
|
||||||
* Keymap (`_user`)
|
|
||||||
|
|
||||||
Each of the functions described below can be defined with a `_kb()` suffix or a `_user()` suffix. We intend for you to use the `_kb()` suffix at the Keyboard/Revision level, while the `_user()` suffix should be used at the Keymap level.
|
|
||||||
|
|
||||||
When defining functions at the Keyboard/Revision level it is important that your `_kb()` implementation call `_user()` before executing anything else- otherwise the keymap level function will never be called.
|
|
||||||
|
|
||||||
# Custom Keycodes
|
|
||||||
|
|
||||||
By far the most common task is to change the behavior of an existing keycode or to create a new keycode. From a code standpoint the mechanism for each is very similar.
|
|
||||||
|
|
||||||
## Defining a New Keycode
|
|
||||||
|
|
||||||
The first step to creating your own custom keycode(s) is to enumerate them. This means both naming them and assigning a unique number to that keycode. Rather than limit custom keycodes to a fixed range of numbers QMK provides the `SAFE_RANGE` macro. You can use `SAFE_RANGE` when enumerating your custom keycodes to guarantee that you get a unique number.
|
|
||||||
|
|
||||||
|
|
||||||
Here is an example of enumerating 2 keycodes. After adding this block to your `keymap.c` you will be able to use `FOO` and `BAR` inside your keymap.
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum my_keycodes {
|
|
||||||
FOO = SAFE_RANGE,
|
|
||||||
BAR
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
These function are called every time a key is pressed or released.
|
|
||||||
|
|
||||||
### Example `process_record_user()` Implementation
|
|
||||||
|
|
||||||
This example does two things. It defines the behavior for a custom keycode called `FOO`, and it supplements our Enter key by playing a tone whenever it is pressed.
|
|
||||||
|
|
||||||
```c
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case FOO:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// Do something when pressed
|
|
||||||
} else {
|
|
||||||
// Do something else when release
|
|
||||||
}
|
|
||||||
return false; // Skip all further processing of this key
|
|
||||||
case KC_ENTER:
|
|
||||||
// Play a tone when enter is pressed
|
|
||||||
if (record->event.pressed) {
|
|
||||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
|
||||||
}
|
|
||||||
return true; // Let QMK send the enter press/release events
|
|
||||||
default:
|
|
||||||
return true; // Process all other keycodes normally
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `process_record_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
|
|
||||||
* Keymap: `bool process_record_user(uint16_t keycode, keyrecord_t *record)`
|
|
||||||
|
|
||||||
The `keycode` argument is whatever is defined in your keymap, eg `MO(1)`, `KC_L`, etc. You should use a `switch...case` block to handle these events.
|
|
||||||
|
|
||||||
The `record` argument contains information about the actual press:
|
|
||||||
|
|
||||||
```c
|
|
||||||
keyrecord_t record {
|
|
||||||
keyevent_t event {
|
|
||||||
keypos_t key {
|
|
||||||
uint8_t col
|
|
||||||
uint8_t row
|
|
||||||
}
|
|
||||||
bool pressed
|
|
||||||
uint16_t time
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# LED Control
|
|
||||||
|
|
||||||
QMK provides methods to read the 5 LEDs defined as part of the HID spec:
|
|
||||||
|
|
||||||
* `USB_LED_NUM_LOCK`
|
|
||||||
* `USB_LED_CAPS_LOCK`
|
|
||||||
* `USB_LED_SCROLL_LOCK`
|
|
||||||
* `USB_LED_COMPOSE`
|
|
||||||
* `USB_LED_KANA`
|
|
||||||
|
|
||||||
These five constants correspond to the positional bits of the host LED state.
|
|
||||||
There are two ways to get the host LED state:
|
|
||||||
|
|
||||||
* by implementing `led_set_user()`
|
|
||||||
* by calling `host_keyboard_leds()`
|
|
||||||
|
|
||||||
## `led_set_user()`
|
|
||||||
|
|
||||||
This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a parameter.
|
|
||||||
Use the `IS_LED_ON(usb_led, led_name)` and `IS_LED_OFF(usb_led, led_name)` macros to check the LED status.
|
|
||||||
|
|
||||||
!> `host_keyboard_leds()` may already reflect a new value before `led_set_user()` is called.
|
|
||||||
|
|
||||||
### Example `led_set_user()` Implementation
|
|
||||||
|
|
||||||
```c
|
|
||||||
void led_set_user(uint8_t usb_led) {
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
|
|
||||||
writePinLow(B0);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B0);
|
|
||||||
}
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
|
|
||||||
writePinLow(B1);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B1);
|
|
||||||
}
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
|
|
||||||
writePinLow(B2);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B2);
|
|
||||||
}
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) {
|
|
||||||
writePinLow(B3);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B3);
|
|
||||||
}
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_KANA)) {
|
|
||||||
writePinLow(B4);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `led_set_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void led_set_kb(uint8_t usb_led)`
|
|
||||||
* Keymap: `void led_set_user(uint8_t usb_led)`
|
|
||||||
|
|
||||||
## `host_keyboard_leds()`
|
|
||||||
|
|
||||||
Call this function to get the last received LED state. This is useful for reading the LED state outside `led_set_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
|
|
||||||
For convenience, you can use the `IS_HOST_LED_ON(led_name)` and `IS_HOST_LED_OFF(led_name)` macros instead of calling and checking `host_keyboard_leds()` directly.
|
|
||||||
|
|
||||||
## Setting Physical LED State
|
|
||||||
|
|
||||||
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
|
|
||||||
|
|
||||||
### Ergodox Boards
|
|
||||||
|
|
||||||
The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
|
|
||||||
|
|
||||||
In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
|
|
||||||
|
|
||||||
Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).
|
|
||||||
|
|
||||||
# Keyboard Initialization Code
|
|
||||||
|
|
||||||
There are several steps in the keyboard initialization process. Depending on what you want to do, it will influence which function you should use.
|
|
||||||
|
|
||||||
These are the three main initialization functions, listed in the order that they're called.
|
|
||||||
|
|
||||||
* `keyboard_pre_init_*` - Happens before most anything is started. Good for hardware setup that you want running very early.
|
|
||||||
* `matrix_init_*` - Happens midway through the firmware's startup process. Hardware is initialized, but features may not be yet.
|
|
||||||
* `keyboard_post_init_*` - Happens at the end of the firmware's startup process. This is where you'd want to put "customization" code, for the most part.
|
|
||||||
|
|
||||||
!> For most people, the `keyboard_post_init_user` function is what you want to call. For instance, this is where you want to set up things for RGB Underglow.
|
|
||||||
|
|
||||||
## Keyboard Pre Initialization code
|
|
||||||
|
|
||||||
This runs very early during startup, even before the USB has been started.
|
|
||||||
|
|
||||||
Shortly after this, the matrix is initialized.
|
|
||||||
|
|
||||||
For most users, this shouldn't be used, as it's primarily for hardware oriented initialization.
|
|
||||||
|
|
||||||
However, if you have hardware stuff that you need initialized, this is the best place for it (such as initializing LED pins).
|
|
||||||
|
|
||||||
### Example `keyboard_pre_init_user()` Implementation
|
|
||||||
|
|
||||||
This example, at the keyboard level, sets up B0, B1, B2, B3, and B4 as LED pins.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void keyboard_pre_init_user(void) {
|
|
||||||
// Call the keyboard pre init code.
|
|
||||||
|
|
||||||
// Set our LED pins as output
|
|
||||||
setPinOutput(B0);
|
|
||||||
setPinOutput(B1);
|
|
||||||
setPinOutput(B2);
|
|
||||||
setPinOutput(B3);
|
|
||||||
setPinOutput(B4);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `keyboard_pre_init_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void keyboard_pre_init_kb(void)`
|
|
||||||
* Keymap: `void keyboard_pre_init_user(void)`
|
|
||||||
|
|
||||||
## Matrix Initialization Code
|
|
||||||
|
|
||||||
This is called when the matrix is initialized, and after some of the hardware has been set up, but before many of the features have been initialized.
|
|
||||||
|
|
||||||
This is useful for setting up stuff that you may need elsewhere, but isn't hardware related nor is dependant on where it's started.
|
|
||||||
|
|
||||||
|
|
||||||
### `matrix_init_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void matrix_init_kb(void)`
|
|
||||||
* Keymap: `void matrix_init_user(void)`
|
|
||||||
|
|
||||||
|
|
||||||
## Keyboard Post Initialization code
|
|
||||||
|
|
||||||
This is ran as the very last task in the keyboard initialization process. This is useful if you want to make changes to certain features, as they should be initialized by this point.
|
|
||||||
|
|
||||||
|
|
||||||
### Example `keyboard_post_init_user()` Implementation
|
|
||||||
|
|
||||||
This example, running after everything else has initialized, sets up the rgb underglow configuration.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void keyboard_post_init_user(void) {
|
|
||||||
// Call the post init code.
|
|
||||||
rgblight_enable_noeeprom(); // enables Rgb, without saving settings
|
|
||||||
rgblight_sethsv_noeeprom(180, 255, 255): // sets the color to teal/cyan without saving
|
|
||||||
rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // sets mode to Fast breathing without saving
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `keyboard_post_init_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void keyboard_post_init_kb(void)`
|
|
||||||
* Keymap: `void keyboard_post_init_user(void)`
|
|
||||||
|
|
||||||
# Matrix Scanning Code
|
|
||||||
|
|
||||||
Whenever possible you should customize your keyboard by using `process_record_*()` and hooking into events that way, to ensure that your code does not have a negative performance impact on your keyboard. However, in rare cases it is necessary to hook into the matrix scanning. Be extremely careful with the performance of code in these functions, as it will be called at least 10 times per second.
|
|
||||||
|
|
||||||
### Example `matrix_scan_*` Implementation
|
|
||||||
|
|
||||||
This example has been deliberately omitted. You should understand enough about QMK internals to write this without an example before hooking into such a performance sensitive area. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/Uq7gcHh).
|
|
||||||
|
|
||||||
### `matrix_scan_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void matrix_scan_kb(void)`
|
|
||||||
* Keymap: `void matrix_scan_user(void)`
|
|
||||||
|
|
||||||
This function gets called at every matrix scan, which is basically as often as the MCU can handle. Be careful what you put here, as it will get run a lot.
|
|
||||||
|
|
||||||
You should use this function if you need custom matrix scanning code. It can also be used for custom status output (such as LEDs or a display) or other functionality that you want to trigger regularly even when the user isn't typing.
|
|
||||||
|
|
||||||
|
|
||||||
# Keyboard Idling/Wake Code
|
|
||||||
|
|
||||||
If the board supports it, it can be "idled", by stopping a number of functions. A good example of this is RGB lights or backlights. This can save on power consumption, or may be better behavior for your keyboard.
|
|
||||||
|
|
||||||
This is controlled by two functions: `suspend_power_down_*` and `suspend_wakeup_init_*`, which are called when the system is board is idled and when it wakes up, respectively.
|
|
||||||
|
|
||||||
|
|
||||||
### Example suspend_power_down_user() and suspend_wakeup_init_user() Implementation
|
|
||||||
|
|
||||||
|
|
||||||
```c
|
|
||||||
void suspend_power_down_user(void) {
|
|
||||||
rgb_matrix_set_suspend_state(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void suspend_wakeup_init_user(void) {
|
|
||||||
rgb_matrix_set_suspend_state(false);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Keyboard suspend/wake Function Documentation
|
|
||||||
|
|
||||||
* 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
|
|
||||||
|
|
||||||
This runs code every time that the layers get changed. This can be useful for layer indication, or custom layer handling.
|
|
||||||
|
|
||||||
### Example `layer_state_set_*` Implementation
|
|
||||||
|
|
||||||
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example
|
|
||||||
|
|
||||||
```c
|
|
||||||
uint32_t layer_state_set_user(uint32_t state) {
|
|
||||||
switch (biton32(state)) {
|
|
||||||
case _RAISE:
|
|
||||||
rgblight_setrgb (0x00, 0x00, 0xFF);
|
|
||||||
break;
|
|
||||||
case _LOWER:
|
|
||||||
rgblight_setrgb (0xFF, 0x00, 0x00);
|
|
||||||
break;
|
|
||||||
case _PLOVER:
|
|
||||||
rgblight_setrgb (0x00, 0xFF, 0x00);
|
|
||||||
break;
|
|
||||||
case _ADJUST:
|
|
||||||
rgblight_setrgb (0x7A, 0x00, 0xFF);
|
|
||||||
break;
|
|
||||||
default: // for any other layers, or the default layer
|
|
||||||
rgblight_setrgb (0x00, 0xFF, 0xFF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### `layer_state_set_*` Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `uint32_t layer_state_set_kb(uint32_t state)`
|
|
||||||
* Keymap: `uint32_t layer_state_set_user(uint32_t state)`
|
|
||||||
|
|
||||||
The `state` is the bitmask of the active layers, as explained in the [Keymap Overview](keymap.md#keymap-layer-status)
|
|
||||||
|
|
||||||
|
|
||||||
# Persistent Configuration (EEPROM)
|
|
||||||
|
|
||||||
This allows you to configure persistent settings for your keyboard. These settings are stored in the EEPROM of your controller, and are retained even after power loss. The settings can be read with `eeconfig_read_kb` and `eeconfig_read_user`, and can be written to using `eeconfig_update_kb` and `eeconfig_update_user`. This is useful for features that you want to be able to toggle (like toggling rgb layer indication). Additionally, you can use `eeconfig_init_kb` and `eeconfig_init_user` to set the default values for the EEPROM.
|
|
||||||
|
|
||||||
The complicated part here, is that there are a bunch of ways that you can store and access data via EEPROM, and there is no "correct" way to do this. However, you only have a DWORD (4 bytes) for each function.
|
|
||||||
|
|
||||||
Keep in mind that EEPROM has a limited number of writes. While this is very high, it's not the only thing writing to the EEPROM, and if you write too often, you can potentially drastically shorten the life of your MCU.
|
|
||||||
|
|
||||||
* If you don't understand the example, then you may want to avoid using this feature, as it is rather complicated.
|
|
||||||
|
|
||||||
### Example Implementation
|
|
||||||
|
|
||||||
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here. This is a complex function, and has a lot going on. In fact, it uses a lot of the above functions to work!
|
|
||||||
|
|
||||||
|
|
||||||
In your keymap.c file, add this to the top:
|
|
||||||
```
|
|
||||||
typedef union {
|
|
||||||
uint32_t raw;
|
|
||||||
struct {
|
|
||||||
bool rgb_layer_change :1;
|
|
||||||
};
|
|
||||||
} user_config_t;
|
|
||||||
|
|
||||||
user_config_t user_config;
|
|
||||||
```
|
|
||||||
|
|
||||||
This sets up a 32 bit structure that we can store settings with in memory, and write to the EEPROM. Using this removes the need to define variables, since they're defined in this structure. Remember that `bool` (boolean) values use 1 bit, `uint8_t` uses 8 bits, `uint16_t` uses up 16 bits. You can mix and match, but changing the order can cause issues, as it will change the values that are read and written.
|
|
||||||
|
|
||||||
We're using `rgb_layer_change`, for the `layer_state_set_*` function, and use `keyboard_post_init_user` and `process_record_user` to configure everything.
|
|
||||||
|
|
||||||
Now, using the `keyboard_post_init_user` code above, you want to add `eeconfig_read_user()` to it, to populate the structure you've just created. And you can then immediately use this structure to control functionality in your keymap. And It should look like:
|
|
||||||
```
|
|
||||||
void keyboard_post_init_user(void) {
|
|
||||||
// Call the keymap level matrix init.
|
|
||||||
|
|
||||||
// Read the user config from EEPROM
|
|
||||||
user_config.raw = eeconfig_read_user();
|
|
||||||
|
|
||||||
// Set default layer, if enabled
|
|
||||||
if (user_config.rgb_layer_change) {
|
|
||||||
rgblight_enable_noeeprom();
|
|
||||||
rgblight_sethsv_noeeprom_cyan();
|
|
||||||
rgblight_mode_noeeprom(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
The above function will use the EEPROM config immediately after reading it, to set the default layer's RGB color. The "raw" value of it is converted in a usable structure based on the "union" that you created above.
|
|
||||||
|
|
||||||
```
|
|
||||||
uint32_t layer_state_set_user(uint32_t state) {
|
|
||||||
switch (biton32(state)) {
|
|
||||||
case _RAISE:
|
|
||||||
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
|
|
||||||
break;
|
|
||||||
case _LOWER:
|
|
||||||
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
|
|
||||||
break;
|
|
||||||
case _PLOVER:
|
|
||||||
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_green(); rgblight_mode_noeeprom(1); }
|
|
||||||
break;
|
|
||||||
case _ADJUST:
|
|
||||||
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_white(); rgblight_mode_noeeprom(1); }
|
|
||||||
break;
|
|
||||||
default: // for any other layers, or the default layer
|
|
||||||
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_cyan(); rgblight_mode_noeeprom(1); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This will cause the RGB underglow to be changed ONLY if the value was enabled. Now to configure this value, create a new keycode for `process_record_user` called `RGB_LYR` and `EPRM`. Additionally, we want to make sure that if you use the normal RGB codes, that it turns off Using the example above, make it look this:
|
|
||||||
```
|
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case FOO:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// Do something when pressed
|
|
||||||
} else {
|
|
||||||
// Do something else when release
|
|
||||||
}
|
|
||||||
return false; // Skip all further processing of this key
|
|
||||||
case KC_ENTER:
|
|
||||||
// Play a tone when enter is pressed
|
|
||||||
if (record->event.pressed) {
|
|
||||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
|
||||||
}
|
|
||||||
return true; // Let QMK send the enter press/release events
|
|
||||||
case EPRM:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
eeconfig_init(); // resets the EEPROM to default
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
|
|
||||||
if (record->event.pressed) {
|
|
||||||
user_config.rgb_layer_change ^= 1; // Toggles the status
|
|
||||||
eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
|
|
||||||
if (user_config.rgb_layer_change) { // if layer state indication is enabled,
|
|
||||||
layer_state_set(layer_state); // then immediately update the layer color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false; break;
|
|
||||||
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
|
|
||||||
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
|
|
||||||
if (user_config.rgb_layer_change) { // only if this is enabled
|
|
||||||
user_config.rgb_layer_change = false; // disable it, and
|
|
||||||
eeconfig_update_user(user_config.raw); // write the setings to EEPROM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; break;
|
|
||||||
default:
|
|
||||||
return true; // Process all other keycodes normally
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
And lastly, you want to add the `eeconfig_init_user` function, so that when the EEPROM is reset, you can specify default values, and even custom actions. For example, if you want to set rgb layer indication by default, and save the default valued.
|
|
||||||
|
|
||||||
```
|
|
||||||
void eeconfig_init_user(void) { // EEPROM is getting reset!
|
|
||||||
user_config.raw = 0;
|
|
||||||
user_config.rgb_layer_change = true; // We want this enabled by default
|
|
||||||
eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
|
|
||||||
|
|
||||||
// use the non noeeprom versions, to write these values to EEPROM too
|
|
||||||
rgblight_enable(); // Enable RGB by default
|
|
||||||
rgblight_sethsv_cyan(); // Set it to CYAN by default
|
|
||||||
rgblight_mode(1); // set to solid by default
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
And you're done. The RGB layer indication will only work if you want it to. And it will be saved, even after unplugging the board. And if you use any of the RGB codes, it will disable the layer indication, so that it stays on the mode and color that you set it to.
|
|
||||||
|
|
||||||
### 'EECONFIG' Function Documentation
|
|
||||||
|
|
||||||
* Keyboard/Revision: `void eeconfig_init_kb(void)`, `uint32_t eeconfig_read_kb(void)` and `void eeconfig_update_kb(uint32_t val)`
|
|
||||||
* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
|
|
||||||
|
|
||||||
The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.
|
|
@ -1,64 +0,0 @@
|
|||||||
# Documentation Best Practices
|
|
||||||
|
|
||||||
This page exists to document best practices when writing documentation for QMK. Following these guidelines will help to keep a consistent tone and style, which will in turn help other people more easily understand QMK.
|
|
||||||
|
|
||||||
# Page Opening
|
|
||||||
|
|
||||||
Your documentation page should generally start with an H1 heading, followed by a 1 paragraph description of what the user will find on this page. Keep in mind that this heading and paragraph will sit next to the Table of Contents, so keep the heading short and avoid long strings with no whitespace.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
# My Page Title
|
|
||||||
|
|
||||||
This page covers my super cool feature. You can use this feature to make coffee, squeeze fresh oj, and have an egg mcmuffin and hashbrowns delivered from your local macca's by drone.
|
|
||||||
```
|
|
||||||
|
|
||||||
# Headings
|
|
||||||
|
|
||||||
Your page should generally have multiple "H1" headings. Only H1 and H2 headings will included in the Table of Contents, so plan them out appropriately. Excess width should be avoided in H1 and H2 headings to prevent the Table of Contents from getting too wide.
|
|
||||||
|
|
||||||
# Styled Hint Blocks
|
|
||||||
|
|
||||||
You can have styled hint blocks drawn around text to draw attention to it.
|
|
||||||
|
|
||||||
### Important
|
|
||||||
|
|
||||||
```
|
|
||||||
!> This is important
|
|
||||||
```
|
|
||||||
|
|
||||||
Renders as:
|
|
||||||
|
|
||||||
!> This is important
|
|
||||||
|
|
||||||
### General Tips
|
|
||||||
|
|
||||||
```
|
|
||||||
?> This is a helpful tip.
|
|
||||||
```
|
|
||||||
|
|
||||||
Renders as:
|
|
||||||
|
|
||||||
?> This is a helpful tip.
|
|
||||||
|
|
||||||
|
|
||||||
# Documenting Features
|
|
||||||
|
|
||||||
If you create a new feature for QMK, create a documentation page for it. It doesn't have to be very long, a few sentences describing your feature and a table listing any relevant keycodes is enough. Here is a basic template:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# My Cool Feature
|
|
||||||
|
|
||||||
This page describes my cool feature. You can use my cool feature to make coffee and order cream and sugar to be delivered via drone.
|
|
||||||
|
|
||||||
## My Cool Feature Keycodes
|
|
||||||
|
|
||||||
|Long Name|Short Name|Description|
|
|
||||||
|---------|----------|-----------|
|
|
||||||
|KC_COFFEE||Make Coffee|
|
|
||||||
|KC_CREAM||Order Cream|
|
|
||||||
|KC_SUGAR||Order Sugar|
|
|
||||||
```
|
|
||||||
|
|
||||||
Place your documentation into `docs/feature_<my_cool_feature>.md`, and add that file to the appropriate place in `docs/_sidebar.md`. If you have added any keycodes be sure to add them to `docs/keycodes.md` with a link back to your feature page.
|
|
@ -1,42 +0,0 @@
|
|||||||
# Documentation Templates
|
|
||||||
|
|
||||||
This page documents the templates you should use when submitting new Keymaps and Keyboards to QMK.
|
|
||||||
|
|
||||||
## Keymap `readme.md` 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.
|
|
||||||
|
|
||||||
Below the image you should write a short description to help people understand your keymap.
|
|
||||||
|
|
||||||
```
|
|
||||||
![Clueboard Layout Image](http://i.imgur.com/7Capi8W.png)
|
|
||||||
|
|
||||||
# Default Clueboard Layout
|
|
||||||
|
|
||||||
This is the default layout that comes flashed on every Clueboard. For the most
|
|
||||||
part it's a straightforward and easy to follow layout. The only unusual key is
|
|
||||||
the key in the upper left, which sends Escape normally, but Grave when any of
|
|
||||||
the Ctrl, Alt, or GUI modifiers are held down.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Keyboard `readme.md` Template
|
|
||||||
|
|
||||||
```
|
|
||||||
# Planck
|
|
||||||
|
|
||||||
![Planck](http://i.imgur.com/q2M3uEU.jpg)
|
|
||||||
|
|
||||||
A compact 40% (12x4) ortholinear keyboard kit made and sold by OLKB and Massdrop. [More info on qmk.fm](http://qmk.fm/planck/)
|
|
||||||
|
|
||||||
Keyboard Maintainer: [Jack Humbert](https://github.com/jackhumbert)
|
|
||||||
Hardware Supported: Planck PCB rev1, rev2, rev3, rev4, Teensy 2.0
|
|
||||||
Hardware Availability: [OLKB.com](https://olkb.com), [Massdrop](https://www.massdrop.com/buy/planck-mechanical-keyboard?mode=guest_open)
|
|
||||||
|
|
||||||
Make example for this keyboard (after setting up your build environment):
|
|
||||||
|
|
||||||
make planck/rev4:default
|
|
||||||
|
|
||||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
|
||||||
```
|
|
||||||
|
|
||||||
There needs to be two spaces at the end of the `Keyboard Maintainer` and `Hardware Supported` lines for it to render correctly with Markdown.
|
|
@ -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)
|
|
@ -1,153 +0,0 @@
|
|||||||
# Frequently Asked Build Questions
|
|
||||||
|
|
||||||
This page covers questions about building QMK. If you haven't yet done so, you should read the [Build Environment Setup](getting_started_build_tools.md) and [Make Instructions](getting_started_make_guide.md) guides.
|
|
||||||
|
|
||||||
## Can't Program on Linux
|
|
||||||
You will need proper permissions to operate a device. For Linux users, see the instructions regarding `udev` rules, below. If you have issues with `udev`, a work-around is to use the `sudo` command. If you are not familiar with this command, check its manual with `man sudo` or [see this webpage](https://linux.die.net/man/8/sudo).
|
|
||||||
|
|
||||||
An example of using `sudo`, when your controller is ATMega32u4:
|
|
||||||
|
|
||||||
$ sudo dfu-programmer atmega32u4 erase --force
|
|
||||||
$ sudo dfu-programmer atmega32u4 flash your.hex
|
|
||||||
$ sudo dfu-programmer atmega32u4 reset
|
|
||||||
|
|
||||||
or just:
|
|
||||||
|
|
||||||
$ sudo make <keyboard>:<keymap>:dfu
|
|
||||||
|
|
||||||
Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible.
|
|
||||||
|
|
||||||
### Linux `udev` Rules
|
|
||||||
On Linux, you'll need proper privileges to access the MCU. You can either use
|
|
||||||
`sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`.
|
|
||||||
|
|
||||||
**/etc/udev/rules.d/50-atmel-dfu.rules:**
|
|
||||||
```
|
|
||||||
# Atmel ATMega32U4
|
|
||||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", MODE:="0666"
|
|
||||||
# Atmel USBKEY AT90USB1287
|
|
||||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", MODE:="0666"
|
|
||||||
# Atmel ATMega32U2
|
|
||||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff0", MODE:="0666"
|
|
||||||
```
|
|
||||||
|
|
||||||
**/etc/udev/rules.d/52-tmk-keyboard.rules:**
|
|
||||||
```
|
|
||||||
# tmk keyboard products https://github.com/tmk/tmk_keyboard
|
|
||||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
|
|
||||||
```
|
|
||||||
**/etc/udev/rules.d/54-input-club-keyboard.rules:**
|
|
||||||
|
|
||||||
```
|
|
||||||
# Input Club keyboard bootloader
|
|
||||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", MODE:="0666"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Serial device is not detected in bootloader mode on Linux
|
|
||||||
Make sure your kernel has appropriate support for your device. If your device uses USB ACM, such as
|
|
||||||
Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices may require `USB_SERIAL` and any of its sub options.
|
|
||||||
|
|
||||||
## Unknown Device for DFU Bootloader
|
|
||||||
|
|
||||||
If you're using Windows to flash your keyboard, and you are running into issues, check the Device Manager. If you see an "Unknown Device" when the keyboard is in "bootloader mode", then you may have a driver issue.
|
|
||||||
|
|
||||||
Re-running the installation script for MSYS2 may help (eg run `./util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue.
|
|
||||||
|
|
||||||
If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, find the device in question, and select the `WinUSB` option, and hit "Reinstall driver". Once you've done that, try flashing your board, again. If that doesn't work, try all of the options, until one works.
|
|
||||||
|
|
||||||
?> There isn't a best option for which driver should be used here. Some options work better on some systems than others. libUSB and WinUSB seem to be the best options here.
|
|
||||||
|
|
||||||
If the bootloader doesn't show up in the list for devices, you may need to enable the "List all devices" option in the `Options` menu, and then find the bootloader in question.
|
|
||||||
|
|
||||||
|
|
||||||
## WINAVR is Obsolete
|
|
||||||
It is no longer recommended and may cause some problem.
|
|
||||||
See [TMK Issue #99](https://github.com/tmk/tmk_keyboard/issues/99).
|
|
||||||
|
|
||||||
## USB VID and PID
|
|
||||||
You can use any ID you want with editing `config.h`. Using any presumably unused ID will be no problem in fact except for very low chance of collision with other product.
|
|
||||||
|
|
||||||
Most boards in QMK use `0xFEED` as the vendor ID. You should look through other keyboards to make sure you pick a unique Product ID.
|
|
||||||
|
|
||||||
Also see this.
|
|
||||||
https://github.com/tmk/tmk_keyboard/issues/150
|
|
||||||
|
|
||||||
You can buy a really unique VID:PID here. I don't think you need this for personal use.
|
|
||||||
- http://www.obdev.at/products/vusb/license.html
|
|
||||||
- http://www.mcselec.com/index.php?page=shop.product_details&flypage=shop.flypage&product_id=92&option=com_phpshop&Itemid=1
|
|
||||||
|
|
||||||
## Cortex: `cstddef: No such file or directory`
|
|
||||||
GCC 4.8 of Ubuntu 14.04 had this problem and had to update to 4.9 with this PPA.
|
|
||||||
https://launchpad.net/~terry.guo/+archive/ubuntu/gcc-arm-embedded
|
|
||||||
|
|
||||||
https://github.com/tmk/tmk_keyboard/issues/212
|
|
||||||
https://github.com/tmk/tmk_keyboard/wiki/mbed-cortex-porting#compile-error-cstddef
|
|
||||||
https://developer.mbed.org/forum/mbed/topic/5205/
|
|
||||||
|
|
||||||
## `clock_prescale_set` and `clock_div_1` Not Available
|
|
||||||
Your toolchain is too old to support the MCU. For example WinAVR 20100110 doesn't support ATMega32u2.
|
|
||||||
|
|
||||||
```
|
|
||||||
Compiling C: ../../tmk_core/protocol/lufa/lufa.c
|
|
||||||
avr-gcc -c -mmcu=atmega32u2 -gdwarf-2 -DF_CPU=16000000UL -DINTERRUPT_CONTROL_ENDPOINT -DBOOTLOADER_SIZE=4096 -DF_USB=16000000UL -DARCH=ARCH_AVR8 -DUSB_DEVICE_ONLY -DUSE_FLASH_DESCRIPTORS -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DFIXED_NUM_CONFIGURATIONS=1 -DPROTOCOL_LUFA -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DVERSION=unknown -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=obj_alps64/protocol/lufa/lufa.lst -I. -I../../tmk_core -I../../tmk_core/protocol/lufa -I../../tmk_core/protocol/lufa/LUFA-git -I../../tmk_core/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_alps64_protocol_lufa_lufa.o.d ../../tmk_core/protocol/lufa/lufa.c -o obj_alps64/protocol/lufa/lufa.o
|
|
||||||
../../tmk_core/protocol/lufa/lufa.c: In function 'setup_mcu':
|
|
||||||
../../tmk_core/protocol/lufa/lufa.c:575: warning: implicit declaration of function 'clock_prescale_set'
|
|
||||||
../../tmk_core/protocol/lufa/lufa.c:575: error: 'clock_div_1' undeclared (first use in this function)
|
|
||||||
../../tmk_core/protocol/lufa/lufa.c:575: error: (Each undeclared identifier is reported only once
|
|
||||||
../../tmk_core/protocol/lufa/lufa.c:575: error: for each function it appears in.)
|
|
||||||
make: *** [obj_alps64/protocol/lufa/lufa.o] Error 1
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## BOOTLOADER_SIZE for AVR
|
|
||||||
Note that Teensy2.0++ bootloader size is 2048byte. Some Makefiles may have wrong comment.
|
|
||||||
|
|
||||||
```
|
|
||||||
# Boot Section Size in *bytes*
|
|
||||||
# Teensy halfKay 512
|
|
||||||
# Teensy++ halfKay 2048
|
|
||||||
# Atmel DFU loader 4096 (TMK Alt Controller)
|
|
||||||
# LUFA bootloader 4096
|
|
||||||
# USBaspLoader 2048
|
|
||||||
OPT_DEFS += -DBOOTLOADER_SIZE=2048
|
|
||||||
```
|
|
||||||
|
|
||||||
## `avr-gcc: internal compiler error: Abort trap: 6 (program cc1)` on MacOS
|
|
||||||
This is an issue with updating on brew, causing symlinks that avr-gcc depend on getting mangled.
|
|
||||||
|
|
||||||
The solution is to remove and reinstall all affected modules.
|
|
||||||
|
|
||||||
```
|
|
||||||
brew rm avr-gcc
|
|
||||||
brew rm dfu-programmer
|
|
||||||
brew rm dfu-util
|
|
||||||
brew rm gcc-arm-none-eabi
|
|
||||||
brew rm avrdude
|
|
||||||
brew install avr-gcc
|
|
||||||
brew install dfu-programmer
|
|
||||||
brew install dfu-util
|
|
||||||
brew install gcc-arm-none-eabi
|
|
||||||
brew install avrdude
|
|
||||||
```
|
|
||||||
|
|
||||||
### avr-gcc 8.1 and LUFA
|
|
||||||
|
|
||||||
If you updated your avr-gcc to above 7 you may see errors involving LUFA. For example:
|
|
||||||
|
|
||||||
`lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h:380:5: error: 'const' attribute on function returning 'void'`
|
|
||||||
|
|
||||||
For now, you need to rollback avr-gcc to 7 in brew.
|
|
||||||
|
|
||||||
```
|
|
||||||
brew uninstall --force avr-gcc
|
|
||||||
brew install avr-gcc@7
|
|
||||||
brew link --force avr-gcc@7
|
|
||||||
```
|
|
||||||
|
|
||||||
### I just flashed my keyboard and it does nothing/keypresses don't register - it's also ARM (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019)
|
|
||||||
Due to how EEPROM works on ARM based chips, saved settings may no longer be valid. This affects the default layers, and *may*, under certain circumstances we are still figuring out, make the keyboard unusable. Resetting the EEPROM will correct this.
|
|
||||||
|
|
||||||
[Planck rev6 reset EEPROM](https://cdn.discordapp.com/attachments/473506116718952450/539284620861243409/planck_rev6_default.bin) can be used to force an eeprom reset. After flashing this image, flash your normal firmware again which should restore your keyboard to _normal_ working order.
|
|
||||||
[Preonic rev3 reset EEPROM](https://cdn.discordapp.com/attachments/473506116718952450/537849497313738762/preonic_rev3_default.bin)
|
|
||||||
|
|
||||||
If bootmagic is enabled in any form, you should be able to do this too (see [Bootmagic docs](feature_bootmagic.md) and keyboard info for specifics on how to do this).
|
|
@ -1,19 +0,0 @@
|
|||||||
# Frequently Asked Questions
|
|
||||||
|
|
||||||
## What is QMK?
|
|
||||||
|
|
||||||
[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).
|
|
||||||
|
|
||||||
### Why the Name Quantum?
|
|
||||||
|
|
||||||
<!-- FIXME -->
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
From a technical standpoint QMK builds upon TMK by adding several new features. Most notably QMK has expanded the number of available keycodes and uses these to implement advanced features like `S()`, `LCTL()`, and `MO()`. You can see a complete list of these keycodes in [Keycodes](keycodes.md).
|
|
||||||
|
|
||||||
From a project and community management standpoint TMK maintains all the officially supported keyboards by himself, with a bit of community support. Separate community maintained forks exist or can be created for other keyboards. Only a few keymaps are provided by default, so users typically don't share keymaps with each other. QMK encourages sharing of both keyboards and keymaps through a centrally managed repository, accepting all pull requests that follow the quality standards. These are mostly community maintained, but the QMK team also helps when necessary.
|
|
||||||
|
|
||||||
Both approaches have their merits and their drawbacks, and code flows freely between TMK and QMK when it makes sense.
|
|
@ -1,213 +0,0 @@
|
|||||||
# Keymap FAQ
|
|
||||||
|
|
||||||
This page covers questions people often have about keymaps. If you haven't you should read [Keymap Overview](keymap.md) first.
|
|
||||||
|
|
||||||
## What Keycodes Can I Use?
|
|
||||||
See [Keycodes](keycodes.md) for an index of keycodes available to you. These link to more extensive documentation when available.
|
|
||||||
|
|
||||||
Keycodes are actually defined in [common/keycode.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/keycode.h).
|
|
||||||
|
|
||||||
## What Are the Default Keycodes?
|
|
||||||
|
|
||||||
There are 3 standard keyboard layouts in use around the world- ANSI, ISO, and JIS. North America primarily uses ANSI, Europe and Africa primarily use ISO, and Japan uses JIS. Regions not mentioned typically use either ANSI or ISO. The keycodes corresponding to these layouts are shown here:
|
|
||||||
|
|
||||||
<!-- Source for this image: http://www.keyboard-layout-editor.com/#/gists/bf431647d1001cff5eff20ae55621e9a -->
|
|
||||||
![Keyboard Layout Image](https://i.imgur.com/5wsh5wM.png)
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
As a quick fix try holding down `Space`+`Backspace` while you plug in your keyboard. This will reset the stored settings on your keyboard, returning those keys to normal operation. If that doesn't work look here:
|
|
||||||
|
|
||||||
* [Bootmagic](feature_bootmagic.md)
|
|
||||||
* [Command](feature_command.md)
|
|
||||||
|
|
||||||
## The Menu Key Isn't Working
|
|
||||||
|
|
||||||
The key found on most modern keyboards that is located between `KC_RGUI` and `KC_RCTL` is actually called `KC_APP`. This is because when that key was invented there was already a key named `MENU` in the relevant standards, so MS chose to call that the `APP` key.
|
|
||||||
|
|
||||||
## `KC_SYSREQ` Isn't Working
|
|
||||||
Use keycode for Print Screen(`KC_PSCREEN` or `KC_PSCR`) instead of `KC_SYSREQ`. Key combination of 'Alt + Print Screen' is recognized as 'System request'.
|
|
||||||
|
|
||||||
See [issue #168](https://github.com/tmk/tmk_keyboard/issues/168) and
|
|
||||||
* http://en.wikipedia.org/wiki/Magic_SysRq_key
|
|
||||||
* http://en.wikipedia.org/wiki/System_request
|
|
||||||
|
|
||||||
## Power Keys Aren't Working
|
|
||||||
|
|
||||||
Somewhat confusingly, there are two "Power" keycodes in QMK: `KC_POWER` in the Keyboard/Keypad HID usage page, and `KC_SYSTEM_POWER` (or `KC_PWR`) in the Consumer page.
|
|
||||||
|
|
||||||
The former is only recognized on macOS, while the latter, `KC_SLEP` and `KC_WAKE` are supported by all three major operating systems, so it is recommended to use those instead. Under Windows, these keys take effect immediately, however on macOS they must be held down until a dialog appears.
|
|
||||||
|
|
||||||
## One Shot Modifier
|
|
||||||
Solves my personal 'the' problem. I often got 'the' or 'THe' wrongly instead of 'The'. One Shot Shift mitigates this for me.
|
|
||||||
https://github.com/tmk/tmk_keyboard/issues/67
|
|
||||||
|
|
||||||
## Modifier/Layer Stuck
|
|
||||||
Modifier keys or layers can be stuck unless layer switching is configured properly.
|
|
||||||
For Modifier keys and layer actions you have to place `KC_TRANS` on same position of destination layer to unregister the modifier key or return to previous layer on release event.
|
|
||||||
|
|
||||||
* https://github.com/tmk/tmk_core/blob/master/doc/keymap.md#31-momentary-switching
|
|
||||||
* http://geekhack.org/index.php?topic=57008.msg1492604#msg1492604
|
|
||||||
* https://github.com/tmk/tmk_keyboard/issues/248
|
|
||||||
|
|
||||||
|
|
||||||
## Mechanical Lock Switch Support
|
|
||||||
|
|
||||||
This feature is for *mechanical lock switch* like [this Alps one](http://deskthority.net/wiki/Alps_SKCL_Lock). You can enable it by adding this to your `config.h`:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define LOCKING_SUPPORT_ENABLE
|
|
||||||
#define LOCKING_RESYNC_ENABLE
|
|
||||||
```
|
|
||||||
|
|
||||||
After enabling this feature use keycodes `KC_LCAP`, `KC_LNUM` and `KC_LSCR` in your keymap instead.
|
|
||||||
|
|
||||||
Old vintage mechanical keyboards occasionally have lock switches but modern ones don't have. ***You don't need this feature in most case and just use keycodes `KC_CAPS`, `KC_NLCK` and `KC_SLCK`.***
|
|
||||||
|
|
||||||
## Input Special Characters Other Than ASCII like Cédille 'Ç'
|
|
||||||
NO UNIVERSAL METHOD TO INPUT THOSE WORKS OVER ALL SYSTEMS. You have to define **MACRO** in way specific to your OS or layout.
|
|
||||||
|
|
||||||
See this post for example **MACRO** code.
|
|
||||||
|
|
||||||
http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478-120.html#p195620
|
|
||||||
|
|
||||||
On **Windows** you can use `AltGr` key or **Alt code**.
|
|
||||||
* http://en.wikipedia.org/wiki/AltGr_key
|
|
||||||
* http://en.wikipedia.org/wiki/Alt_code
|
|
||||||
|
|
||||||
On **Mac** OS defines `Option` key combinations.
|
|
||||||
* http://en.wikipedia.org/wiki/Option_key#Alternative_keyboard_input
|
|
||||||
|
|
||||||
On **Xorg** you can use `compose` key, instead.
|
|
||||||
* http://en.wikipedia.org/wiki/Compose_key
|
|
||||||
|
|
||||||
And see this for **Unicode** input.
|
|
||||||
* http://en.wikipedia.org/wiki/Unicode_input
|
|
||||||
|
|
||||||
## `Fn` Key on macOS
|
|
||||||
|
|
||||||
Unlike most Fn keys, the one on Apple keyboards actually has its own keycode... sort of. It takes the place of the sixth keycode in a basic 6KRO HID report -- so an Apple keyboard is in fact only 5KRO.
|
|
||||||
|
|
||||||
It is technically possible to get QMK to send this key. However, doing so requires modification of the report format to add the state of the Fn key.
|
|
||||||
Even worse, it is not recognized unless the keyboard's VID and PID match that of a real Apple keyboard. The legal issues that official QMK support for this feature may create mean it is unlikely to happen.
|
|
||||||
|
|
||||||
See [this issue](https://github.com/qmk/qmk_firmware/issues/2179) for detailed information.
|
|
||||||
|
|
||||||
|
|
||||||
## Media Control Keys in Mac OSX
|
|
||||||
#### KC_MNXT and KC_MPRV Does Not Work on Mac
|
|
||||||
Use `KC_MFFD`(`KC_MEDIA_FAST_FORWARD`) and `KC_MRWD`(`KC_MEDIA_REWIND`) instead of `KC_MNXT` and `KC_MPRV`.
|
|
||||||
See https://github.com/tmk/tmk_keyboard/issues/195
|
|
||||||
|
|
||||||
|
|
||||||
## Keys Supported in Mac OSX?
|
|
||||||
You can know which keycodes are supported in OSX from this source code.
|
|
||||||
|
|
||||||
`usb_2_adb_keymap` array maps Keyboard/Keypad Page usages to ADB scancodes(OSX internal keycodes).
|
|
||||||
|
|
||||||
https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-606.1.7/IOHIDFamily/Cosmo_USB2ADB.c
|
|
||||||
|
|
||||||
And `IOHIDConsumer::dispatchConsumerEvent` handles Consumer page usages.
|
|
||||||
|
|
||||||
https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-606.1.7/IOHIDFamily/IOHIDConsumer.cpp
|
|
||||||
|
|
||||||
|
|
||||||
## JIS Keys in Mac OSX
|
|
||||||
Japanese JIS keyboard specific keys like `無変換(Muhenkan)`, `変換(Henkan)`, `ひらがな(hiragana)` are not recognized on OSX. You can use **Seil** to enable those keys, try following options.
|
|
||||||
|
|
||||||
* Enable NFER Key on PC keyboard
|
|
||||||
* Enable XFER Key on PC keyboard
|
|
||||||
* Enable KATAKANA Key on PC keyboard
|
|
||||||
|
|
||||||
https://pqrs.org/osx/karabiner/seil.html
|
|
||||||
|
|
||||||
|
|
||||||
## RN-42 Bluetooth Doesn't Work with Karabiner
|
|
||||||
Karabiner - Keymapping tool on Mac OSX - ignores inputs from RN-42 module by default. You have to enable this option to make Karabiner working with your keyboard.
|
|
||||||
https://github.com/tekezo/Karabiner/issues/403#issuecomment-102559237
|
|
||||||
|
|
||||||
See these for the detail of this problem.
|
|
||||||
https://github.com/tmk/tmk_keyboard/issues/213
|
|
||||||
https://github.com/tekezo/Karabiner/issues/403
|
|
||||||
|
|
||||||
|
|
||||||
## Esc and <code>`</code> on a Single Key
|
|
||||||
|
|
||||||
See the [Grave Escape](feature_grave_esc.md) feature.
|
|
||||||
|
|
||||||
## Arrow on Right Modifier Keys with Dual-Role
|
|
||||||
This turns right modifier keys into arrow keys when the keys are tapped while still modifiers when the keys are hold. In TMK the dual-role function is dubbed **TAP**.
|
|
||||||
```
|
|
||||||
|
|
||||||
#include "keymap_common.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Arrow keys on right modifier keys with TMK dual role feature
|
|
||||||
*
|
|
||||||
* https://github.com/tmk/tmk_core/blob/master/doc/keymap.md#213-modifier-with-tap-keydual-role
|
|
||||||
* https://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys
|
|
||||||
*/
|
|
||||||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
/* 0: qwerty */
|
|
||||||
[0] = LAYOUT( \
|
|
||||||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NUHS,BSPC, \
|
|
||||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
|
|
||||||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \
|
|
||||||
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH,FN0, ESC, \
|
|
||||||
FN4, LGUI,LALT, SPC, APP, FN2, FN1, FN3),
|
|
||||||
[1] = LAYOUT( \
|
|
||||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS,TRNS, \
|
|
||||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,\
|
|
||||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
|
||||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN5, TRNS, \
|
|
||||||
TRNS,TRNS,TRNS, TRNS, TRNS,FN7, FN6, FN8),
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint16_t PROGMEM fn_actions[] = {
|
|
||||||
[0] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_UP),
|
|
||||||
[1] = ACTION_MODS_TAP_KEY(MOD_RGUI, KC_DOWN),
|
|
||||||
[2] = ACTION_MODS_TAP_KEY(MOD_RALT, KC_LEFT),
|
|
||||||
[3] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_RIGHT),
|
|
||||||
[4] = ACTION_LAYER_MOMENTARY(1),
|
|
||||||
[5] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_PGUP),
|
|
||||||
[6] = ACTION_MODS_TAP_KEY(MOD_RGUI, KC_PGDN),
|
|
||||||
[7] = ACTION_MODS_TAP_KEY(MOD_RALT, KC_HOME),
|
|
||||||
[8] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_END),
|
|
||||||
};
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Dual-role key: https://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys
|
|
||||||
|
|
||||||
|
|
||||||
## Eject on Mac OSX
|
|
||||||
`KC_EJCT` keycode works on OSX. https://github.com/tmk/tmk_keyboard/issues/250
|
|
||||||
It seems Windows 10 ignores the code and Linux/Xorg recognizes but has no mapping by default.
|
|
||||||
|
|
||||||
Not sure what keycode Eject is on genuine Apple keyboard actually. HHKB uses `F20` for Eject key(`Fn+f`) on Mac mode but this is not same as Apple Eject keycode probably.
|
|
||||||
|
|
||||||
|
|
||||||
## What's `weak_mods` and `real_mods` in `action_util.c`
|
|
||||||
___TO BE IMPROVED___
|
|
||||||
|
|
||||||
real_mods is intended to retains state of real/physical modifier key state, while
|
|
||||||
weak_mods retains state of virtual or temporary modifiers which should not affect state real modifier key.
|
|
||||||
|
|
||||||
Let's say you hold down physical left shift key and type ACTION_MODS_KEY(LSHIFT, KC_A),
|
|
||||||
|
|
||||||
with weak_mods,
|
|
||||||
* (1) hold down left shift: real_mods |= MOD_BIT(LSHIFT)
|
|
||||||
* (2) press ACTION_MODS_KEY(LSHIFT, KC_A): weak_mods |= MOD_BIT(LSHIFT)
|
|
||||||
* (3) release ACTION_MODS_KEY(LSHIFT, KC_A): weak_mods &= ~MOD_BIT(LSHIFT)
|
|
||||||
real_mods still keeps modifier state.
|
|
||||||
|
|
||||||
without weak mods,
|
|
||||||
* (1) hold down left shift: real_mods |= MOD_BIT(LSHIFT)
|
|
||||||
* (2) press ACTION_MODS_KEY(LSHIFT, KC_A): real_mods |= MOD_BIT(LSHIFT)
|
|
||||||
* (3) release ACTION_MODS_KEY(LSHIFT, KC_A): real_mods &= ~MOD_BIT(LSHIFT)
|
|
||||||
here real_mods lost state for 'physical left shift'.
|
|
||||||
|
|
||||||
weak_mods is ORed with real_mods when keyboard report is sent.
|
|
||||||
https://github.com/tmk/tmk_core/blob/master/common/action_util.c#L57
|
|
@ -1,328 +0,0 @@
|
|||||||
# 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](https://github.com/qmk/qmk_firmware/blob/master/docs/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
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------|-------------------------------|----------------------------------------------------|
|
|
||||||
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|
|
||||||
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|
|
||||||
|`LALT(kc)`|`A(kc)` |Hold Left Alt and press `kc` |
|
|
||||||
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|
|
||||||
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|
|
||||||
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|
|
||||||
|`RALT(kc)`|`ALGR(kc)` |Hold Right Alt and press `kc` |
|
|
||||||
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|
|
||||||
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|
|
||||||
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|
|
||||||
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|
|
||||||
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|
|
||||||
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc`|
|
|
||||||
|
|
||||||
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 `set_oneshot_layer(ONESHOT_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:
|
|
||||||
|
|
||||||
- `SHFT_T(KC_A)` Down
|
|
||||||
- `KC_X` Down
|
|
||||||
- `KC_X` Up
|
|
||||||
- `SHFT_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`.
|
|
||||||
|
|
||||||
## 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:
|
|
||||||
|
|
||||||
- `SHFT_T(KC_A)` Down
|
|
||||||
- `KC_X` Down
|
|
||||||
- `SHFT_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`.
|
|
||||||
|
|
||||||
## 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:
|
|
||||||
|
|
||||||
- SHFT_T(KC_A) Down
|
|
||||||
- SHFT_T(KC_A) Up
|
|
||||||
- SHFT_T(KC_A) Down
|
|
||||||
- wait more than tapping term...
|
|
||||||
- SHFT_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).
|
|
||||||
|
|
||||||
## Retro Tapping
|
|
||||||
|
|
||||||
To enable `retro tapping`, add the following to your `config.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define RETRO_TAPPING
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
@ -1,320 +0,0 @@
|
|||||||
# Audio
|
|
||||||
|
|
||||||
Your keyboard can make sounds! If you've got a Planck, Preonic, or basically any AVR keyboard that allows access to certain PWM-capable pins, you can hook up a simple speaker and make it beep. You can use those beeps to indicate layer transitions, modifiers, special keys, or just to play some funky 8bit tunes.
|
|
||||||
|
|
||||||
Up to two simultaneous audio voices are supported, one driven by timer 1 and another driven by timer 3. The following pins can be defined as audio outputs in config.h:
|
|
||||||
|
|
||||||
Timer 1:
|
|
||||||
`#define B5_AUDIO`
|
|
||||||
`#define B6_AUDIO`
|
|
||||||
`#define B7_AUDIO`
|
|
||||||
|
|
||||||
Timer 3:
|
|
||||||
`#define C4_AUDIO`
|
|
||||||
`#define C5_AUDIO`
|
|
||||||
`#define C6_AUDIO`
|
|
||||||
|
|
||||||
If you add `AUDIO_ENABLE = yes` to your `rules.mk`, there's a couple different sounds that will automatically be enabled without any other configuration:
|
|
||||||
|
|
||||||
```
|
|
||||||
STARTUP_SONG // plays when the keyboard starts up (audio.c)
|
|
||||||
GOODBYE_SONG // plays when you press the RESET key (quantum.c)
|
|
||||||
AG_NORM_SONG // plays when you press AG_NORM (quantum.c)
|
|
||||||
AG_SWAP_SONG // plays when you press AG_SWAP (quantum.c)
|
|
||||||
MUSIC_ON_SONG // plays when music mode is activated (process_music.c)
|
|
||||||
MUSIC_OFF_SONG // plays when music mode is deactivated (process_music.c)
|
|
||||||
CHROMATIC_SONG // plays when the chromatic music mode is selected (process_music.c)
|
|
||||||
GUITAR_SONG // plays when the guitar music mode is selected (process_music.c)
|
|
||||||
VIOLIN_SONG // plays when the violin music mode is selected (process_music.c)
|
|
||||||
MAJOR_SONG // plays when the major music mode is selected (process_music.c)
|
|
||||||
```
|
|
||||||
|
|
||||||
You can override the default songs by doing something like this in your `config.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
#define STARTUP_SONG SONG(STARTUP_SOUND)
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
A full list of sounds can be found in [quantum/audio/song_list.h](https://github.com/qmk/qmk_firmware/blob/master/quantum/audio/song_list.h) - feel free to add your own to this list! All available notes can be seen in [quantum/audio/musical_notes.h](https://github.com/qmk/qmk_firmware/blob/master/quantum/audio/musical_notes.h).
|
|
||||||
|
|
||||||
To play a custom sound at a particular time, you can define a song like this (near the top of the file):
|
|
||||||
|
|
||||||
```c
|
|
||||||
float my_song[][2] = SONG(QWERTY_SOUND);
|
|
||||||
```
|
|
||||||
|
|
||||||
And then play your song like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
PLAY_SONG(my_song);
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can play it in a loop like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
PLAY_LOOP(my_song);
|
|
||||||
```
|
|
||||||
|
|
||||||
It's advised that you wrap all audio features in `#ifdef AUDIO_ENABLE` / `#endif` to avoid causing problems when audio isn't built into the keyboard.
|
|
||||||
|
|
||||||
The available keycodes for audio are:
|
|
||||||
|
|
||||||
* `AU_ON` - Turn Audio Feature on
|
|
||||||
* `AU_OFF` - Turn Audio Feature off
|
|
||||||
* `AU_TOG` - Toggle Audio Feature state
|
|
||||||
|
|
||||||
!> These keycodes turn all of the audio functionality on and off. Turning it off means that audio feedback, audio clicky, music mode, etc. are disabled, completely.
|
|
||||||
|
|
||||||
## ARM Audio Volume
|
|
||||||
|
|
||||||
For ARM devices, you can adjust the DAC sample values. If your board is too loud for you or your coworkers, you can set the max using `DAC_SAMPLE_MAX` in your `config.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define DAC_SAMPLE_MAX 65535U
|
|
||||||
```
|
|
||||||
|
|
||||||
## Music Mode
|
|
||||||
|
|
||||||
The music mode maps your columns to a chromatic scale, and your rows to octaves. This works best with ortholinear keyboards, but can be made to work with others. All keycodes less than `0xFF` get blocked, so you won't type while playing notes - if you have special keys/mods, those will still work. A work-around for this is to jump to a different layer with KC_NOs before (or after) enabling music mode.
|
|
||||||
|
|
||||||
Recording is experimental due to some memory issues - if you experience some weird behavior, unplugging/replugging your keyboard will fix things.
|
|
||||||
|
|
||||||
Keycodes available:
|
|
||||||
|
|
||||||
* `MU_ON` - Turn music mode on
|
|
||||||
* `MU_OFF` - Turn music mode off
|
|
||||||
* `MU_TOG` - Toggle music mode
|
|
||||||
* `MU_MOD` - Cycle through the music modes:
|
|
||||||
* `CHROMATIC_MODE` - Chromatic scale, row changes the octave
|
|
||||||
* `GUITAR_MODE` - Chromatic scale, but the row changes the string (+5 st)
|
|
||||||
* `VIOLIN_MODE` - Chromatic scale, but the row changes the string (+7 st)
|
|
||||||
* `MAJOR_MODE` - Major scale
|
|
||||||
|
|
||||||
In music mode, the following keycodes work differently, and don't pass through:
|
|
||||||
|
|
||||||
* `LCTL` - start a recording
|
|
||||||
* `LALT` - stop recording/stop playing
|
|
||||||
* `LGUI` - play recording
|
|
||||||
* `KC_UP` - speed-up playback
|
|
||||||
* `KC_DOWN` - slow-down playback
|
|
||||||
|
|
||||||
The pitch standard (`PITCH_STANDARD_A`) is 440.0f by default - to change this, add something like this to your `config.h`:
|
|
||||||
|
|
||||||
#define PITCH_STANDARD_A 432.0f
|
|
||||||
|
|
||||||
You can completely disable Music Mode as well. This is useful, if you're pressed for space on your controller. To disable it, add this to your `config.h`:
|
|
||||||
|
|
||||||
#define NO_MUSIC_MODE
|
|
||||||
|
|
||||||
### Music Mask
|
|
||||||
|
|
||||||
By default, `MUSIC_MASK` is set to `keycode < 0xFF` which means keycodes less than `0xFF` are turned into notes, and don't output anything. You can change this by defining this in your `config.h` like this:
|
|
||||||
|
|
||||||
#define MUSIC_MASK keycode != KC_NO
|
|
||||||
|
|
||||||
Which will capture all keycodes - be careful, this will get you stuck in music mode until you restart your keyboard!
|
|
||||||
|
|
||||||
For a more advanced way to control which keycodes should still be processed, you can use `music_mask_kb(keycode)` in `<keyboard>.c` and `music_mask_user(keycode)` in your `keymap.c`:
|
|
||||||
|
|
||||||
bool music_mask_user(uint16_t keycode) {
|
|
||||||
switch (keycode) {
|
|
||||||
case RAISE:
|
|
||||||
case LOWER:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Things that return false are not part of the mask, and are always processed.
|
|
||||||
|
|
||||||
### Music Map
|
|
||||||
|
|
||||||
By default, the Music Mode uses the columns and row to determine the scale for the keys. For a board that uses a rectangular matrix that matches the keyboard layout, this is just fine. However, for boards that use a more complicated matrix (such as the Planck Rev6, or many split keyboards) this would result in a very skewed experience.
|
|
||||||
|
|
||||||
However, the Music Map option allows you to remap the scaling for the music mode, so it fits the layout, and is more natural.
|
|
||||||
|
|
||||||
To enable this feature, add `#define MUSIC_MAP` to your `config.h` file, and then you will want to add a `uint8_t music_map` to your keyboard's `c` file, or your `keymap.c`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_ortho_4x12(
|
|
||||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
|
||||||
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
|
||||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
You will want to use whichever `LAYOUT` macro that your keyboard uses here. This maps it to the correct key location. Start in the bottom left of the keyboard layout, and move to the right, and then upwards. Fill in all the entries until you have a complete matrix.
|
|
||||||
|
|
||||||
You can look at the [Planck Keyboard](https://github.com/qmk/qmk_firmware/blob/e9ace1487887c1f8b4a7e8e6d87c322988bec9ce/keyboards/planck/planck.c#L24-L29) as an example of how to implement this.
|
|
||||||
|
|
||||||
## Audio Click
|
|
||||||
|
|
||||||
This adds a click sound each time you hit a button, to simulate click sounds from the keyboard. And the sounds are slightly different for each keypress, so it doesn't sound like a single long note, if you type rapidly.
|
|
||||||
|
|
||||||
* `CK_TOGG` - Toggles the status (will play sound if enabled)
|
|
||||||
* `CK_ON` - Turns on Audio Click (plays sound)
|
|
||||||
* `CK_OFF` - Turns off Audio Click (doesn't play sound)
|
|
||||||
* `CK_RST` - Resets the frequency to the default state (plays sound at default frequency)
|
|
||||||
* `CK_UP` - Increases the frequency of the clicks (plays sound at new frequency)
|
|
||||||
* `CK_DOWN` - Decreases the frequency of the clicks (plays sound at new frequency)
|
|
||||||
|
|
||||||
|
|
||||||
The feature is disabled by default, to save space. To enable it, add this to your `config.h`:
|
|
||||||
|
|
||||||
#define AUDIO_CLICKY
|
|
||||||
|
|
||||||
|
|
||||||
You can configure the default, min and max frequencies, the stepping and built in randomness by defining these values:
|
|
||||||
|
|
||||||
| Option | Default Value | Description |
|
|
||||||
|--------|---------------|-------------|
|
|
||||||
| `AUDIO_CLICKY_FREQ_DEFAULT` | 440.0f | Sets the default/starting audio frequency for the clicky sounds. |
|
|
||||||
| `AUDIO_CLICKY_FREQ_MIN` | 65.0f | Sets the lowest frequency (under 60f are a bit buggy). |
|
|
||||||
| `AUDIO_CLICKY_FREQ_MAX` | 1500.0f | Sets the the highest frequency. Too high may result in coworkers attacking you. |
|
|
||||||
| `AUDIO_CLICKY_FREQ_FACTOR` | 1.18921f| Sets the stepping of UP/DOWN key codes. |
|
|
||||||
| `AUDIO_CLICKY_FREQ_RANDOMNESS` | 0.05f | Sets a factor of randomness for the clicks, Setting this to `0f` will make each click identical, and `1.0f` will make this sound much like the 90's computer screen scrolling/typing effect. |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## MIDI Functionality
|
|
||||||
|
|
||||||
This is still a WIP, but check out `quantum/process_keycode/process_midi.c` to see what's happening. Enable from the Makefile.
|
|
||||||
|
|
||||||
|
|
||||||
## Audio Keycodes
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------|---------|----------------------------------|
|
|
||||||
|`AU_ON` | |Audio mode on |
|
|
||||||
|`AU_OFF` | |Audio mode off |
|
|
||||||
|`AU_TOG` | |Toggles Audio mode |
|
|
||||||
|`CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|
|
||||||
|`CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|
|
||||||
|`CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|
|
||||||
|`CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|
|
||||||
|`MU_ON` | |Turns on Music Mode |
|
|
||||||
|`MU_OFF` | |Turns off Music Mode |
|
|
||||||
|`MU_TOG` | |Toggles Music Mode |
|
|
||||||
|`MU_MOD` | |Cycles through the music modes |
|
|
||||||
|
|
||||||
<!-- FIXME: this formatting needs work
|
|
||||||
|
|
||||||
## Audio
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
AU_ON,
|
|
||||||
AU_OFF,
|
|
||||||
AU_TOG,
|
|
||||||
|
|
||||||
#ifdef FAUXCLICKY_ENABLE
|
|
||||||
FC_ON,
|
|
||||||
FC_OFF,
|
|
||||||
FC_TOG,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Music mode on/off/toggle
|
|
||||||
MU_ON,
|
|
||||||
MU_OFF,
|
|
||||||
MU_TOG,
|
|
||||||
|
|
||||||
// Music voice iterate
|
|
||||||
MUV_IN,
|
|
||||||
MUV_DE,
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
### Midi
|
|
||||||
|
|
||||||
#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
|
||||||
MI_ON, // send midi notes when music mode is enabled
|
|
||||||
MI_OFF, // don't send midi notes when music mode is enabled
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MIDI_TONE_MIN,
|
|
||||||
MIDI_TONE_MAX
|
|
||||||
|
|
||||||
MI_C = MIDI_TONE_MIN,
|
|
||||||
MI_Cs,
|
|
||||||
MI_Db = MI_Cs,
|
|
||||||
MI_D,
|
|
||||||
MI_Ds,
|
|
||||||
MI_Eb = MI_Ds,
|
|
||||||
MI_E,
|
|
||||||
MI_F,
|
|
||||||
MI_Fs,
|
|
||||||
MI_Gb = MI_Fs,
|
|
||||||
MI_G,
|
|
||||||
MI_Gs,
|
|
||||||
MI_Ab = MI_Gs,
|
|
||||||
MI_A,
|
|
||||||
MI_As,
|
|
||||||
MI_Bb = MI_As,
|
|
||||||
MI_B,
|
|
||||||
|
|
||||||
MIDI_TONE_KEYCODE_OCTAVES > 1
|
|
||||||
|
|
||||||
where x = 1-5:
|
|
||||||
MI_C_x,
|
|
||||||
MI_Cs_x,
|
|
||||||
MI_Db_x = MI_Cs_x,
|
|
||||||
MI_D_x,
|
|
||||||
MI_Ds_x,
|
|
||||||
MI_Eb_x = MI_Ds_x,
|
|
||||||
MI_E_x,
|
|
||||||
MI_F_x,
|
|
||||||
MI_Fs_x,
|
|
||||||
MI_Gb_x = MI_Fs_x,
|
|
||||||
MI_G_x,
|
|
||||||
MI_Gs_x,
|
|
||||||
MI_Ab_x = MI_Gs_x,
|
|
||||||
MI_A_x,
|
|
||||||
MI_As_x,
|
|
||||||
MI_Bb_x = MI_As_x,
|
|
||||||
MI_B_x,
|
|
||||||
|
|
||||||
MI_OCT_Nx 1-2
|
|
||||||
MI_OCT_x 0-7
|
|
||||||
MIDI_OCTAVE_MIN = MI_OCT_N2,
|
|
||||||
MIDI_OCTAVE_MAX = MI_OCT_7,
|
|
||||||
MI_OCTD, // octave down
|
|
||||||
MI_OCTU, // octave up
|
|
||||||
|
|
||||||
MI_TRNS_Nx 1-6
|
|
||||||
MI_TRNS_x 0-6
|
|
||||||
MIDI_TRANSPOSE_MIN = MI_TRNS_N6,
|
|
||||||
MIDI_TRANSPOSE_MAX = MI_TRNS_6,
|
|
||||||
MI_TRNSD, // transpose down
|
|
||||||
MI_TRNSU, // transpose up
|
|
||||||
|
|
||||||
MI_VEL_x 1-10
|
|
||||||
MIDI_VELOCITY_MIN = MI_VEL_1,
|
|
||||||
MIDI_VELOCITY_MAX = MI_VEL_9,
|
|
||||||
MI_VELD, // velocity down
|
|
||||||
MI_VELU, // velocity up
|
|
||||||
|
|
||||||
MI_CHx 1-16
|
|
||||||
MIDI_CHANNEL_MIN = MI_CH1
|
|
||||||
MIDI_CHANNEL_MAX = MI_CH16,
|
|
||||||
MI_CHD, // previous channel
|
|
||||||
MI_CHU, // next channel
|
|
||||||
|
|
||||||
MI_ALLOFF, // all notes off
|
|
||||||
|
|
||||||
MI_SUS, // sustain
|
|
||||||
MI_PORT, // portamento
|
|
||||||
MI_SOST, // sostenuto
|
|
||||||
MI_SOFT, // soft pedal
|
|
||||||
MI_LEG, // legato
|
|
||||||
|
|
||||||
MI_MOD, // modulation
|
|
||||||
MI_MODSD, // decrease modulation speed
|
|
||||||
MI_MODSU, // increase modulation speed
|
|
||||||
#endif // MIDI_ADVANCED
|
|
||||||
|
|
||||||
-->
|
|
@ -1,167 +0,0 @@
|
|||||||
# Auto Shift: Why Do We Need a Shift Key?
|
|
||||||
|
|
||||||
Tap a key and you get its character. Tap a key, but hold it *slightly* longer
|
|
||||||
and you get its shifted state. Voilà! No shift key needed!
|
|
||||||
|
|
||||||
## Why Auto Shift?
|
|
||||||
|
|
||||||
Many people suffer from various forms of RSI. A common cause is stretching your
|
|
||||||
fingers repetitively long distances. For us on the keyboard, the pinky does that
|
|
||||||
all too often when reaching for the shift key. Auto Shift looks to alleviate that
|
|
||||||
problem.
|
|
||||||
|
|
||||||
## How Does It Work?
|
|
||||||
|
|
||||||
When you tap a key, it stays depressed for a short period of time before it is
|
|
||||||
then released. This depressed time is a different length for everyone. Auto Shift
|
|
||||||
defines a constant `AUTO_SHIFT_TIMEOUT` which is typically set to twice your
|
|
||||||
normal pressed state time. When you press a key, a timer starts and then stops
|
|
||||||
when you release the key. If the time depressed is greater than or equal to the
|
|
||||||
`AUTO_SHIFT_TIMEOUT`, then a shifted version of the key is emitted. If the time
|
|
||||||
is less than the `AUTO_SHIFT_TIMEOUT` time, then the normal state is emitted.
|
|
||||||
|
|
||||||
## Are There Limitations to Auto Shift?
|
|
||||||
|
|
||||||
Yes, unfortunately.
|
|
||||||
|
|
||||||
1. Key repeat will cease to work. For example, before if you wanted 20 'a'
|
|
||||||
characters, you could press and hold the 'a' key for a second or two. This no
|
|
||||||
longer works with Auto Shift because it is timing your depressed time instead
|
|
||||||
of emitting a depressed key state to your operating system.
|
|
||||||
2. You will have characters that are shifted when you did not intend on shifting, and
|
|
||||||
other characters you wanted shifted, but were not. This simply comes down to
|
|
||||||
practice. As we get in a hurry, we think we have hit the key long enough
|
|
||||||
for a shifted version, but we did not. On the other hand, we may think we are
|
|
||||||
tapping the keys, but really we have held it for a little longer than
|
|
||||||
anticipated.
|
|
||||||
|
|
||||||
## How Do I Enable Auto Shift?
|
|
||||||
|
|
||||||
Add to your `rules.mk` in the keymap folder:
|
|
||||||
|
|
||||||
AUTO_SHIFT_ENABLE = yes
|
|
||||||
|
|
||||||
If no `rules.mk` exists, you can create one.
|
|
||||||
|
|
||||||
Then compile and install your new firmware with Auto Key enabled! That's it!
|
|
||||||
|
|
||||||
## Modifiers
|
|
||||||
|
|
||||||
By default, Auto Shift is disabled for any key press that is accompanied by one or more
|
|
||||||
modifiers. Thus, Ctrl+A that you hold for a really long time is not the same
|
|
||||||
as Ctrl+Shift+A.
|
|
||||||
|
|
||||||
You can re-enable Auto Shift for modifiers by adding another rule to your `rules.mk`
|
|
||||||
|
|
||||||
AUTO_SHIFT_MODIFIERS = yes
|
|
||||||
|
|
||||||
In which case, Ctrl+A held past the `AUTO_SHIFT_TIMEOUT` will be sent as Ctrl+Shift+A
|
|
||||||
|
|
||||||
## Configuring Auto Shift
|
|
||||||
|
|
||||||
If desired, there is some configuration that can be done to change the
|
|
||||||
behavior of Auto Shift. This is done by setting various variables the
|
|
||||||
`config.h` file located in your keymap folder. If no `config.h` file exists, you can create one.
|
|
||||||
|
|
||||||
A sample is
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_H
|
|
||||||
#define CONFIG_USER_H
|
|
||||||
|
|
||||||
#include "../../config.h"
|
|
||||||
|
|
||||||
#define AUTO_SHIFT_TIMEOUT 150
|
|
||||||
#define NO_AUTO_SHIFT_SPECIAL
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
### AUTO_SHIFT_TIMEOUT (Value in ms)
|
|
||||||
|
|
||||||
This controls how long you have to hold a key before you get the shifted state.
|
|
||||||
Obviously, this is different for everyone. For the common person, a setting of
|
|
||||||
135 to 150 works great. However, one should start with a value of at least 175, which
|
|
||||||
is the default value. Then work down from there. The idea is to have the shortest time required to get the shifted state without having false positives.
|
|
||||||
|
|
||||||
Play with this value until things are perfect. Many find that all will work well
|
|
||||||
at a given value, but one or two keys will still emit the shifted state on
|
|
||||||
occasion. This is simply due to habit and holding some keys a little longer
|
|
||||||
than others. Once you find this value, work on tapping your problem keys a little
|
|
||||||
quicker than normal and you will be set.
|
|
||||||
|
|
||||||
?> Auto Shift has three special keys that can help you get this value right very quick. See "Auto Shift Setup" for more details!
|
|
||||||
|
|
||||||
### NO_AUTO_SHIFT_SPECIAL (simple define)
|
|
||||||
|
|
||||||
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
|
|
||||||
and /?
|
|
||||||
|
|
||||||
### NO_AUTO_SHIFT_NUMERIC (simple define)
|
|
||||||
|
|
||||||
Do not Auto Shift numeric keys, zero through nine.
|
|
||||||
|
|
||||||
### NO_AUTO_SHIFT_ALPHA (simple define)
|
|
||||||
|
|
||||||
Do not Auto Shift alpha characters, which include A through Z.
|
|
||||||
|
|
||||||
## Using Auto Shift Setup
|
|
||||||
|
|
||||||
This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
|
|
||||||
|
|
||||||
### Setup
|
|
||||||
|
|
||||||
Map three keys temporarily in your keymap:
|
|
||||||
|
|
||||||
| Key Name | Description |
|
|
||||||
|----------|-----------------------------------------------------|
|
|
||||||
| KC_ASDN | Lower the Auto Shift timeout variable (down) |
|
|
||||||
| KC_ASUP | Raise the Auto Shift timeout variable (up) |
|
|
||||||
| KC_ASRP | Report your current Auto Shift timeout value |
|
|
||||||
| KC_ASON | Turns on the Auto Shift Function |
|
|
||||||
| KC_ASOFF | Turns off the Auto Shift Function |
|
|
||||||
| KC_ASTG | Toggles the state of the Auto Shift feature |
|
|
||||||
|
|
||||||
Compile and upload your new firmware.
|
|
||||||
|
|
||||||
### Use
|
|
||||||
|
|
||||||
It is important to note that during these tests, you should be typing
|
|
||||||
completely normal and with no intention of shifted keys.
|
|
||||||
|
|
||||||
1. Type multiple sentences of alphabetical letters.
|
|
||||||
2. Observe any upper case letters.
|
|
||||||
3. If there are none, press the key you have mapped to `KC_ASDN` to decrease
|
|
||||||
time Auto Shift timeout value and go back to step 1.
|
|
||||||
4. If there are some upper case letters, decide if you need to work on tapping
|
|
||||||
those keys with less down time, or if you need to increase the timeout.
|
|
||||||
5. If you decide to increase the timeout, press the key you have mapped to
|
|
||||||
`KC_ASUP` and go back to step 1.
|
|
||||||
6. Once you are happy with your results, press the key you have mapped to
|
|
||||||
`KC_ASRP`. The keyboard will type by itself the value of your
|
|
||||||
`AUTO_SHIFT_TIMEOUT`.
|
|
||||||
7. Update `AUTO_SHIFT_TIMEOUT` in your `config.h` with the value reported.
|
|
||||||
8. Remove `AUTO_SHIFT_SETUP` from your `config.h`.
|
|
||||||
9. Remove the key bindings `KC_ASDN`, `KC_ASUP` and `KC_ASRP`.
|
|
||||||
10. Compile and upload your new firmware.
|
|
||||||
|
|
||||||
#### An Example Run
|
|
||||||
|
|
||||||
hello world. my name is john doe. i am a computer programmer playing with
|
|
||||||
keyboards right now.
|
|
||||||
|
|
||||||
[PRESS KC_ASDN quite a few times]
|
|
||||||
|
|
||||||
heLLo woRLd. mY nAMe is JOHn dOE. i AM A compUTeR proGRaMMER PlAYiNG witH
|
|
||||||
KEYboArDS RiGHT NOw.
|
|
||||||
|
|
||||||
[PRESS KC_ASUP a few times]
|
|
||||||
|
|
||||||
hello world. my name is john Doe. i am a computer programmer playing with
|
|
||||||
keyboarDs right now.
|
|
||||||
|
|
||||||
[PRESS KC_ASRP]
|
|
||||||
|
|
||||||
115
|
|
||||||
|
|
||||||
The keyboard typed `115` which represents your current `AUTO_SHIFT_TIMEOUT`
|
|
||||||
value. You are now set! Practice on the *D* key a little bit that showed up
|
|
||||||
in the testing and you'll be golden.
|
|
@ -1,76 +0,0 @@
|
|||||||
# Backlighting
|
|
||||||
|
|
||||||
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
|
|
||||||
|
|
||||||
The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Most keyboards have backlighting enabled by default if they support it, but if it is not working for you, check that your `rules.mk` includes the following:
|
|
||||||
|
|
||||||
```make
|
|
||||||
BACKLIGHT_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
You should then be able to use the keycodes below to change the backlight level.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|---------|------------------------------------------|
|
|
||||||
|`BL_TOGG`|Turn the backlight on or off |
|
|
||||||
|`BL_STEP`|Cycle through backlight levels |
|
|
||||||
|`BL_ON` |Set the backlight to max brightness |
|
|
||||||
|`BL_OFF` |Turn the backlight off |
|
|
||||||
|`BL_INC` |Increase the backlight level |
|
|
||||||
|`BL_DEC` |Decrease the backlight level |
|
|
||||||
|`BL_BRTG`|Toggle backlight breathing |
|
|
||||||
|
|
||||||
## Caveats
|
|
||||||
|
|
||||||
This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously use multiple different coloured LEDs on a keyboard.
|
|
||||||
|
|
||||||
Hardware PWM is only supported on certain pins of the MCU, so if the backlighting is not connected to one of them, a software implementation will be used, and backlight breathing will not be available. Currently the supported pins are `B5`, `B6`, `B7`, and `C6`.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
To change the behaviour of the backlighting, `#define` these in your `config.h`:
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
|
||||||
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
|
||||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 15 excluding off) |
|
|
||||||
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
|
||||||
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if hardware PWM is used |
|
|
||||||
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
|
||||||
|
|
||||||
## Hardware PWM Implementation
|
|
||||||
|
|
||||||
When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
|
||||||
The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
|
|
||||||
In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus the brightness, where `0x0000` is completely off and `0xFFFF` is completely on.
|
|
||||||
|
|
||||||
The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
|
|
||||||
In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
|
|
||||||
|
|
||||||
## Backlight Functions
|
|
||||||
|
|
||||||
|Function |Description |
|
|
||||||
|----------|-----------------------------------------------------------|
|
|
||||||
|`backlight_toggle()` |Turn the backlight on or off |
|
|
||||||
|`backlight_enable()` |Turn the backlight on |
|
|
||||||
|`backlight_disable()` |Turn the backlight off |
|
|
||||||
|`backlight_step()` |Cycle through backlight levels |
|
|
||||||
|`backlight_increase()` |Increase the backlight level |
|
|
||||||
|`backlight_decrease()` |Decrease the backlight level |
|
|
||||||
|`backlight_level(x)` |Sets the backlight level to specified level |
|
|
||||||
|`get_backlight_level()` |Return the current backlight level |
|
|
||||||
|`is_backlight_enabled()`|Return whether the backlight is currently on |
|
|
||||||
|
|
||||||
### Backlight Breathing Functions
|
|
||||||
|
|
||||||
|Function |Description |
|
|
||||||
|----------|----------------------------------------------------------|
|
|
||||||
|`breathing_toggle()` |Turn the backlight breathing on or off |
|
|
||||||
|`breathing_enable()` |Turns on backlight breathing |
|
|
||||||
|`breathing_disable()` |Turns off backlight breathing |
|
|
@ -1,47 +0,0 @@
|
|||||||
# Bluetooth
|
|
||||||
|
|
||||||
## Bluetooth Known Supported Hardware
|
|
||||||
|
|
||||||
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1 Qmk has support for RN-42 HID Firmware and Bluefruit EZ Key the later of which is not produced anymore. For more recent BLE protocols currently only the Adafruit Bluefruit SPI friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support Mouse Input.
|
|
||||||
|
|
||||||
|Board |Bluetooth Protocol |Connection Type |Rules.mk |Bluetooth Chip|
|
|
||||||
|----------------------------------------------------------------|----------------------------|----------------|---------------------------|--------------|
|
|
||||||
|[Adafruit EzKey HID]("https://www.adafruit.com/product/1535") |Bluetooth Classic | UART | BLUETOOTH = AdafruitEZKey | |
|
|
||||||
|Rover Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic | UART | BLUETOOTH = RN42 | RN-42 |
|
|
||||||
|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy | SPI | BLUETOOTH = AdafruitBLE | nRF5182 |
|
|
||||||
|
|
||||||
Not Supported Yet but possible:
|
|
||||||
* [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479). [Possible tmk implementation found in](https://github.com/tmk/tmk_keyboard/issues/514)
|
|
||||||
* HC-05 boards flashed with RN-42 firmware. They apparently both use the CSR BC417 Chip. Flashing it with RN-42 firmware gives it HID capability.
|
|
||||||
* [Sparkfun Bluetooth mate](https://www.sparkfun.com/products/14839)
|
|
||||||
* HM-13 based boards
|
|
||||||
|
|
||||||
### Adafruit BLE SPI Friend
|
|
||||||
Currently The only bluetooth chipset supported by QMK is the Adafruit Bluefruit SPI Friend. It's a Nordic nRF5182 based chip running Adafruit's custom firmware. Data is transmitted via Adafruit's SDEP over Hardware SPI. The [Feather 32u4 Bluefruit LE](https://www.adafruit.com/product/2829) is supported as it's an AVR mcu connected via SPI to the Nordic BLE chip with Adafruit firmware. If Building a custom board with the SPI friend it would be easiest to just use the pin selection that the 32u4 feather uses but you can change the pins in the config.h options with the following defines:
|
|
||||||
* #define AdafruitBleResetPin D4
|
|
||||||
* #define AdafruitBleCSPin B4
|
|
||||||
* #define AdafruitBleIRQPin E6
|
|
||||||
|
|
||||||
A Bluefruit UART friend can be converted to an SPI friend, however this [requires](https://github.com/qmk/qmk_firmware/issues/2274) some reflashing and soldering directly to the MDBT40 chip.
|
|
||||||
|
|
||||||
## Adafruit EZ-Key hid
|
|
||||||
This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
|
|
||||||
|
|
||||||
|
|
||||||
<!-- FIXME: Document bluetooth support more completely. -->
|
|
||||||
## Bluetooth Rules.mk Options
|
|
||||||
Use only one of these
|
|
||||||
* BLUETOOTH_ENABLE = yes (Legacy Option)
|
|
||||||
* BLUETOOTH = RN42
|
|
||||||
* BLUETOOTH = AdafruitEZKey
|
|
||||||
* BLUETOOTH = AdafruitBLE
|
|
||||||
|
|
||||||
## Bluetooth Keycodes
|
|
||||||
|
|
||||||
This is used when multiple keyboard outputs can be selected. Currently this only allows for switching between USB and Bluetooth on keyboards that support both.
|
|
||||||
|
|
||||||
|Name |Description |
|
|
||||||
|----------|----------------------------------------------|
|
|
||||||
|`OUT_AUTO`|Automatically switch between USB and Bluetooth|
|
|
||||||
|`OUT_USB` |USB only |
|
|
||||||
|`OUT_BT` |Bluetooth only |
|
|
@ -1,153 +0,0 @@
|
|||||||
# Bootmagic
|
|
||||||
|
|
||||||
There are three separate but related features that allow you to change the behavior of your keyboard without reflashing. While each of them have similar functionality, it is accessed in different ways depending on how your keyboard is configured.
|
|
||||||
|
|
||||||
**Bootmagic** is a system for configuring your keyboard while it initializes. To trigger a Bootmagic command, hold down the Bootmagic key and one or more command keys.
|
|
||||||
|
|
||||||
**Bootmagic Keycodes** are prefixed with `MAGIC_`, and allow you to access the Bootmagic functionality *after* your keyboard has initialized. To use the keycodes, assign them to your keymap as you would any other keycode.
|
|
||||||
|
|
||||||
**Command**, formerly known as **Magic**, is another feature that allows you to control different aspects of your keyboard. While it shares some functionality with Bootmagic, it also allows you to do things that Bootmagic does not, such as printing version information to the console. For more information, see [Command](feature_command.md).
|
|
||||||
|
|
||||||
On some keyboards Bootmagic is disabled by default. If this is the case, it must be explicitly enabled in your `rules.mk` with:
|
|
||||||
|
|
||||||
```make
|
|
||||||
BOOTMAGIC_ENABLE = full
|
|
||||||
```
|
|
||||||
|
|
||||||
?> You may see `yes` being used in place of `full`, and this is okay. However, `yes` is deprecated, and ideally `full` (or `lite`) should be used instead.
|
|
||||||
|
|
||||||
Additionally, you can use [Bootmagic Lite](#bootmagic-lite) (a scaled down, very basic version of Bootmagic) by adding the following to your `rules.mk` file:
|
|
||||||
|
|
||||||
```make
|
|
||||||
BOOTMAGIC_ENABLE = lite
|
|
||||||
```
|
|
||||||
|
|
||||||
## Hotkeys
|
|
||||||
|
|
||||||
Hold down the Bootmagic key (Space by default) and the desired hotkey while plugging in your keyboard. For example, holding Space+`B` should cause it to enter the bootloader.
|
|
||||||
|
|
||||||
|Hotkey |Description |
|
|
||||||
|------------------|---------------------------------------------|
|
|
||||||
|Escape |Ignore Bootmagic configuration in EEPROM |
|
|
||||||
|`B` |Enter the bootloader |
|
|
||||||
|`D` |Toggle debugging over serial |
|
|
||||||
|`X` |Toggle key matrix debugging |
|
|
||||||
|`K` |Toggle keyboard debugging |
|
|
||||||
|`M` |Toggle mouse debugging |
|
|
||||||
|Backspace |Clear the EEPROM |
|
|
||||||
|Caps Lock |Toggle treating Caps Lock as Left Control |
|
|
||||||
|Left Control |Toggle swapping Caps Lock and Left Control |
|
|
||||||
|Left Alt |Toggle swapping Left Alt and Left GUI |
|
|
||||||
|Right Alt |Toggle swapping Right Alt and Right GUI |
|
|
||||||
|Left GUI |Toggle the GUI keys (useful when gaming) |
|
|
||||||
|<code>`</code>|Toggle swapping <code>`</code> and Escape|
|
|
||||||
|`\` |Toggle swapping `\` and Backspace |
|
|
||||||
|`N` |Toggle N-Key Rollover (NKRO) |
|
|
||||||
|`0` |Make layer 0 the default layer |
|
|
||||||
|`1` |Make layer 1 the default layer |
|
|
||||||
|`2` |Make layer 2 the default layer |
|
|
||||||
|`3` |Make layer 3 the default layer |
|
|
||||||
|`4` |Make layer 4 the default layer |
|
|
||||||
|`5` |Make layer 5 the default layer |
|
|
||||||
|`6` |Make layer 6 the default layer |
|
|
||||||
|`7` |Make layer 7 the default layer |
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Keycode |Aliases |Description |
|
|
||||||
|----------------------------------|---------|------------------------------------------|
|
|
||||||
|`MAGIC_CAPSLOCK_TO_CONTROL` | |Treat Caps Lock as Left Control |
|
|
||||||
|`MAGIC_UNCAPSLOCK_TO_CONTROL` | |Stop treating Caps Lock as Left Control |
|
|
||||||
|`MAGIC_HOST_NKRO` | |Force N-Key Rollover (NKRO) on |
|
|
||||||
|`MAGIC_UNHOST_NKRO` | |Force NKRO off |
|
|
||||||
|`MAGIC_TOGGLE_NKRO` | |Turn NKRO on or off |
|
|
||||||
|`MAGIC_NO_GUI` | |Disable the GUI keys (useful when gaming) |
|
|
||||||
|`MAGIC_UNNO_GUI` | |Enable the GUI keys |
|
|
||||||
|`MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides (for macOS)|
|
|
||||||
|`MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Left Alt and Left GUI |
|
|
||||||
|`MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Left Alt and GUI swap |
|
|
||||||
|`MAGIC_SWAP_BACKSLASH_BACKSPACE` | |Swap `\` and Backspace |
|
|
||||||
|`MAGIC_UNSWAP_BACKSLASH_BACKSPACE`| |Unswap `\` and Backspace |
|
|
||||||
|`MAGIC_SWAP_CONTROL_CAPSLOCK` | |Swap Left Control and Caps Lock |
|
|
||||||
|`MAGIC_UNSWAP_CONTROL_CAPSLOCK` | |Unswap Left Control and Caps Lock |
|
|
||||||
|`MAGIC_SWAP_GRAVE_ESC` | |Swap <code>`</code> and Escape |
|
|
||||||
|`MAGIC_UNSWAP_GRAVE_ESC` | |Unswap <code>`</code> and Escape |
|
|
||||||
|`MAGIC_SWAP_LALT_LGUI` | |Swap Left Alt and Left GUI |
|
|
||||||
|`MAGIC_UNSWAP_LALT_LGUI` | |Unswap Left Alt and Left GUI |
|
|
||||||
|`MAGIC_SWAP_RALT_RGUI` | |Swap Right Alt and Right GUI |
|
|
||||||
|`MAGIC_UNSWAP_RALT_RGUI` | |Unswap Right Alt and Right GUI |
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
If you would like to change the hotkey assignments for Bootmagic, `#define` these in your `config.h` at either the keyboard or keymap level.
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|----------------------------------------|-------------|---------------------------------------------------|
|
|
||||||
|`BOOTMAGIC_KEY_SALT` |`KC_SPACE` |The Bootmagic key |
|
|
||||||
|`BOOTMAGIC_KEY_SKIP` |`KC_ESC` |Ignore Bootmagic configuration in EEPROM |
|
|
||||||
|`BOOTMAGIC_KEY_EEPROM_CLEAR` |`KC_BSPACE` |Clear the EEPROM configuration |
|
|
||||||
|`BOOTMAGIC_KEY_BOOTLOADER` |`KC_B` |Enter the bootloader |
|
|
||||||
|`BOOTMAGIC_KEY_DEBUG_ENABLE` |`KC_D` |Toggle debugging over serial |
|
|
||||||
|`BOOTMAGIC_KEY_DEBUG_MATRIX` |`KC_X` |Toggle matrix debugging |
|
|
||||||
|`BOOTMAGIC_KEY_DEBUG_KEYBOARD` |`KC_K` |Toggle keyboard debugging |
|
|
||||||
|`BOOTMAGIC_KEY_DEBUG_MOUSE` |`KC_M` |Toggle mouse debugging |
|
|
||||||
|`BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK` |`KC_LCTRL` |Swap Left Control and Caps Lock |
|
|
||||||
|`BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL` |`KC_CAPSLOCK`|Toggle treating Caps Lock as Left Control |
|
|
||||||
|`BOOTMAGIC_KEY_SWAP_LALT_LGUI` |`KC_LALT` |Toggle swapping Left Alt and Left GUI (for macOS) |
|
|
||||||
|`BOOTMAGIC_KEY_SWAP_RALT_RGUI` |`KC_RALT` |Toggle swapping Right Alt and Right GUI (for macOS)|
|
|
||||||
|`BOOTMAGIC_KEY_NO_GUI` |`KC_LGUI` |Toggle the GUI keys (useful when gaming) |
|
|
||||||
|`BOOTMAGIC_KEY_SWAP_GRAVE_ESC` |`KC_GRAVE` |Toggle swapping <code>`</code> and Escape |
|
|
||||||
|`BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE`|`KC_BSLASH` |Toggle swapping `\` and Backspace |
|
|
||||||
|`BOOTMAGIC_HOST_NKRO` |`KC_N` |Toggle N-Key Rollover (NKRO) |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_0` |`KC_0` |Make layer 0 the default layer |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_1` |`KC_1` |Make layer 1 the default layer |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_2` |`KC_2` |Make layer 2 the default layer |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_3` |`KC_3` |Make layer 3 the default layer |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_4` |`KC_4` |Make layer 4 the default layer |
|
|
||||||
|`BOOTMAGIC_KEY_DEFAULT_LAYER_5` |`KC_5` |Make layer 5 the default layer |
|
|
||||||
|`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
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
```make
|
|
||||||
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:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define BOOTMAGIC_LITE_ROW 0
|
|
||||||
#define BOOTMAGIC_LITE_COLUMN 1
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, these are set to 0 and 0, which is usually the "ESC" key on a majority of keyboards.
|
|
||||||
|
|
||||||
And to trigger the bootloader, you hold this key down when plugging the keyboard in. Just the single key.
|
|
||||||
|
|
||||||
!> Using bootmagic lite will **always reset** the EEPROM, so you will lose any settings that have been saved.
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
To replace the function, all you need to do is add something like this to your code:
|
|
||||||
|
|
||||||
```c
|
|
||||||
void bootmagic_lite(void) {
|
|
||||||
matrix_scan();
|
|
||||||
wait_ms(DEBOUNCING_DELAY * 2);
|
|
||||||
matrix_scan();
|
|
||||||
|
|
||||||
if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
|
|
||||||
// Jump to bootloader.
|
|
||||||
bootloader_jump();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
@ -1,89 +0,0 @@
|
|||||||
# Combos
|
|
||||||
|
|
||||||
The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the tapping term would hit `ESC` instead, or have it perform even more complex tasks.
|
|
||||||
|
|
||||||
To enable this feature, yu need to add `COMBO_ENABLE = yes` to your `rules.mk`.
|
|
||||||
|
|
||||||
Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using).
|
|
||||||
<!-- At this time, this is necessary -->
|
|
||||||
|
|
||||||
Also, by default, the tapping term for the Combos is set to the same value as `TAPPING_TERM` (200 by default on most boards). But you can specify a different value by defining it in your `config.h`. For instance: `#define COMBO_TERM 300` would set the time out period for combos to 300ms.
|
|
||||||
|
|
||||||
Then, your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and it's resulting action.
|
|
||||||
|
|
||||||
```c
|
|
||||||
const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END};
|
|
||||||
combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)};
|
|
||||||
```
|
|
||||||
|
|
||||||
This will send "Escape" if you hit the A and B keys.
|
|
||||||
|
|
||||||
!> This method only supports [basic keycodes](keycodes_basic.md). See the examples for more control.
|
|
||||||
!> You cannot reuse (share) keys in combos. Each key should only belong to a single combo.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
If you want to add a list, then you'd use something like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum combos {
|
|
||||||
AB_ESC,
|
|
||||||
JK_TAB
|
|
||||||
};
|
|
||||||
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
|
|
||||||
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
|
|
||||||
|
|
||||||
combo_t key_combos[COMBO_COUNT] = {
|
|
||||||
[AB_ESC] = COMBO(ab_combo, KC_ESC),
|
|
||||||
[JK_TAB] = COMBO(jk_combo, KC_TAB)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
For a more complicated implementation, you can use the `process_combo_event` function to add custom handling.
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum combo_events {
|
|
||||||
ZC_COPY,
|
|
||||||
XV_PASTE
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END};
|
|
||||||
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};
|
|
||||||
|
|
||||||
combo_t key_combos[COMBO_COUNT] = {
|
|
||||||
[ZC_COPY] = COMBO_ACTION(copy_combo),
|
|
||||||
[XV_PASTE] = COMBO_ACTION(paste_combo),
|
|
||||||
};
|
|
||||||
|
|
||||||
void process_combo_event(uint8_t combo_index, bool pressed) {
|
|
||||||
switch(combo_index) {
|
|
||||||
case ZC_COPY:
|
|
||||||
if (pressed) {
|
|
||||||
register_code(KC_LCTL);
|
|
||||||
register_code(KC_C);
|
|
||||||
unregister_code(KC_C);
|
|
||||||
unregister_code(KC_LCTL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XV_PASTE:
|
|
||||||
if (pressed) {
|
|
||||||
register_code(KC_LCTL);
|
|
||||||
register_code(KC_V);
|
|
||||||
unregister_code(KC_V);
|
|
||||||
unregister_code(KC_LCTL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This will send Ctrl+C if you hit Z and C, and Ctrl+V if you hit X and V. But you could change this to do stuff like change layers, play sounds, or change settings.
|
|
||||||
|
|
||||||
## Additional Configuration
|
|
||||||
|
|
||||||
If you're using long combos, or even longer combos, you may run into issues with this, as the structure may not be large enough to accommodate what you're doing.
|
|
||||||
|
|
||||||
In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file.
|
|
||||||
|
|
||||||
You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`.
|
|
@ -1,51 +0,0 @@
|
|||||||
# Command
|
|
||||||
|
|
||||||
Command, formerly known as Magic, is a way to change your keyboard's behavior without having to flash or unplug it to use [Bootmagic](feature_bootmagic.md). There is a lot of overlap between this functionality and the [Bootmagic Keycodes](feature_bootmagic.md#keycodes). Wherever possible we encourage you to use that feature instead of Command.
|
|
||||||
|
|
||||||
On some keyboards Command is disabled by default. If this is the case, it must be explicitly enabled in your `rules.mk`:
|
|
||||||
|
|
||||||
```make
|
|
||||||
COMMAND_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
To use Command, hold down the key combination defined by the `IS_COMMAND()` macro. By default this is Left Shift+Right Shift. Then, press the key corresponding to the command you want. For example, to output the current QMK version to the QMK Toolbox console, press Left Shift+Right Shift+`V`.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
If you would like to change the key assignments for Command, `#define` these in your `config.h` at either the keyboard or keymap level. All keycode assignments here must omit the `KC_` prefix.
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|------------------------------------|---------------------------------------------------------------------------|------------------------------------------------|
|
|
||||||
|`IS_COMMAND()` |<code>(get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))</code>|The key combination to activate Command |
|
|
||||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS` |`true` |Set default layer with the Function row |
|
|
||||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS` |`true` |Set default layer with the number keys |
|
|
||||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM`|`false` |Set default layer with `MAGIC_KEY_LAYER0..9` |
|
|
||||||
|`MAGIC_KEY_DEBUG` |`D` |Toggle debugging over serial |
|
|
||||||
|`MAGIC_KEY_DEBUG_MATRIX` |`X` |Toggle key matrix debugging |
|
|
||||||
|`MAGIC_KEY_DEBUG_KBD` |`K` |Toggle keyboard debugging |
|
|
||||||
|`MAGIC_KEY_DEBUG_MOUSE` |`M` |Toggle mouse debugging |
|
|
||||||
|`MAGIC_KEY_CONSOLE` |`C` |Enable the Command console |
|
|
||||||
|`MAGIC_KEY_VERSION` |`V` |Print the running QMK version to the console |
|
|
||||||
|`MAGIC_KEY_STATUS` |`S` |Print the current keyboard status to the console|
|
|
||||||
|`MAGIC_KEY_HELP` |`H` |Print Command help to the console |
|
|
||||||
|`MAGIC_KEY_HELP_ALT` |`SLASH` |Print Command help to the console (alternate) |
|
|
||||||
|`MAGIC_KEY_LAYER0` |`0` |Make layer 0 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER0_ALT` |`GRAVE` |Make layer 0 the default layer (alternate) |
|
|
||||||
|`MAGIC_KEY_LAYER1` |`1` |Make layer 1 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER2` |`2` |Make layer 2 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER3` |`3` |Make layer 3 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER4` |`4` |Make layer 4 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER5` |`5` |Make layer 5 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER6` |`6` |Make layer 6 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER7` |`7` |Make layer 7 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER8` |`8` |Make layer 8 the default layer |
|
|
||||||
|`MAGIC_KEY_LAYER9` |`9` |Make layer 9 the default layer |
|
|
||||||
|`MAGIC_KEY_BOOTLOADER` |`B` |Jump to bootloader |
|
|
||||||
|`MAGIC_KEY_BOOTLOADER_ALT` |`ESC` |Jump to bootloader (alternate) |
|
|
||||||
|`MAGIC_KEY_LOCK` |`CAPS` |Lock the keyboard so nothing can be typed |
|
|
||||||
|`MAGIC_KEY_EEPROM` |`E` |Print stored EEPROM config to the console |
|
|
||||||
|`MAGIC_KEY_EEPROM_CLEAR` |`BSPACE` |Clear the EEPROM |
|
|
||||||
|`MAGIC_KEY_NKRO` |`N` |Toggle N-Key Rollover (NKRO) |
|
|
||||||
|`MAGIC_KEY_SLEEP_LED` |`Z` |Toggle LED when computer is sleeping |
|
|
@ -1,39 +0,0 @@
|
|||||||
# Debounce algorithm
|
|
||||||
|
|
||||||
QMK supports multiple debounce algorithms through its debounce API.
|
|
||||||
|
|
||||||
The logic for which debounce method called is below. It checks various defines that you have set in rules.mk
|
|
||||||
|
|
||||||
```
|
|
||||||
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
|
|
||||||
DEBOUNCE_TYPE?= sym_g
|
|
||||||
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
|
|
||||||
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
|
|
||||||
endif
|
|
||||||
```
|
|
||||||
|
|
||||||
# Debounce selection
|
|
||||||
|
|
||||||
| DEBOUNCE_TYPE | Description | What else is needed |
|
|
||||||
| ------------- | --------------------------------------------------- | ----------------------------- |
|
|
||||||
| Not defined | Use the default algorithm, currently sym_g | Nothing |
|
|
||||||
| custom | Use your own debounce.c | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions |
|
|
||||||
| anything_else | Use another algorithm from quantum/debounce/* | Nothing |
|
|
||||||
|
|
||||||
**Regarding split keyboards**:
|
|
||||||
The debounce code is compatible with split keyboards.
|
|
||||||
|
|
||||||
# Use your own debouncing code
|
|
||||||
* Set ```DEBOUNCE_TYPE = custom ```.
|
|
||||||
* Add ```SRC += debounce.c```
|
|
||||||
* Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples.
|
|
||||||
* Debouncing occurs after every raw matrix scan.
|
|
||||||
* Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly.
|
|
||||||
|
|
||||||
# Changing between included debouncing methods
|
|
||||||
You can either use your own code, by including your own debounce.c, or switch to another included one.
|
|
||||||
Included debounce methods are:
|
|
||||||
* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key
|
|
||||||
* sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE_DELAY``` milliseconds of no changes has occured, all input changes are pushed.
|
|
||||||
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
# Dynamic Macros: Record and Replay Macros in Runtime
|
|
||||||
|
|
||||||
QMK supports temporary macros created on the fly. We call these Dynamic Macros. They are defined by the user from the keyboard and are lost when the keyboard is unplugged or otherwise rebooted.
|
|
||||||
|
|
||||||
You can store one or two macros and they may have a combined total of 128 keypresses. You can increase this size at the cost of RAM.
|
|
||||||
|
|
||||||
To enable them, first add a new element to the end of your `keycodes` enum — `DYNAMIC_MACRO_RANGE`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum keycodes {
|
|
||||||
QWERTY = SAFE_RANGE,
|
|
||||||
COLEMAK,
|
|
||||||
DVORAK,
|
|
||||||
PLOVER,
|
|
||||||
LOWER,
|
|
||||||
RAISE,
|
|
||||||
BACKLIT,
|
|
||||||
EXT_PLV,
|
|
||||||
DYNAMIC_MACRO_RANGE,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Your `keycodes` enum may have a slightly different name. You must add `DYNAMIC_MACRO_RANGE` as the last element because `dynamic_macros.h` will add some more keycodes after it.
|
|
||||||
|
|
||||||
Below it, include the `dynamic_macro.h` header:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "dynamic_macro.h"`
|
|
||||||
```
|
|
||||||
|
|
||||||
Add the following keys to your keymap:
|
|
||||||
|
|
||||||
* `DYN_REC_START1` — start recording the macro 1,
|
|
||||||
* `DYN_REC_START2` — start recording the macro 2,
|
|
||||||
* `DYN_MACRO_PLAY1` — replay the macro 1,
|
|
||||||
* `DYN_MACRO_PLAY2` — replay the macro 2,
|
|
||||||
* `DYN_REC_STOP` — finish the macro that is currently being recorded.
|
|
||||||
|
|
||||||
Add the following code to the very beginning of your `process_record_user()` function:
|
|
||||||
|
|
||||||
```c
|
|
||||||
if (!process_record_dynamic_macro(keycode, record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
That should be everything necessary. To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`. To finish the recording, press the `DYN_REC_STOP` layer button. To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`.
|
|
||||||
|
|
||||||
Note that it's possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again.
|
|
||||||
|
|
||||||
For users of the earlier versions of dynamic macros: It is still possible to finish the macro recording using just the layer modifier used to access the dynamic macro keys, without a dedicated `DYN_REC_STOP` key. If you want this behavior back, use the following snippet instead of the one above:
|
|
||||||
|
|
||||||
```c
|
|
||||||
uint16_t macro_kc = (keycode == MO(_DYN) ? DYN_REC_STOP : keycode);
|
|
||||||
|
|
||||||
if (!process_record_dynamic_macro(macro_kc, record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If the LEDs start blinking during the recording with each keypress, it means there is no more space for the macro in the macro buffer. To fit the macro in, either make the other macro shorter (they share the same buffer) or increase the buffer size by setting the `DYNAMIC_MACRO_SIZE` preprocessor macro (default value: 128; please read the comments for it in the header).
|
|
||||||
|
|
||||||
For the details about the internals of the dynamic macros, please read the comments in the `dynamic_macro.h` header.
|
|
@ -1,52 +0,0 @@
|
|||||||
# Encoders
|
|
||||||
|
|
||||||
Basic encoders are supported by adding this to your `rules.mk`:
|
|
||||||
|
|
||||||
ENCODER_ENABLE = yes
|
|
||||||
|
|
||||||
and this to your `config.h`:
|
|
||||||
|
|
||||||
#define NUMBER_OF_ENCODERS 1
|
|
||||||
#define ENCODERS_PAD_A { B12 }
|
|
||||||
#define ENCODERS_PAD_B { B13 }
|
|
||||||
|
|
||||||
Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.:
|
|
||||||
|
|
||||||
#define ENCODERS_PAD_A { encoder1a, encoder2a }
|
|
||||||
#define ENCODERS_PAD_B { encoder1b, encoder2b }
|
|
||||||
|
|
||||||
If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions.
|
|
||||||
|
|
||||||
Additionally, the resolution can be specified in the same file (the default & suggested is 4):
|
|
||||||
|
|
||||||
#define ENCODER_RESOLUTION 4
|
|
||||||
|
|
||||||
## Callbacks
|
|
||||||
|
|
||||||
The callback functions can be inserted into your `<keyboard>.c`:
|
|
||||||
|
|
||||||
void encoder_update_kb(uint8_t index, bool clockwise) {
|
|
||||||
encoder_update_user(index, clockwise);
|
|
||||||
}
|
|
||||||
|
|
||||||
or `keymap.c`:
|
|
||||||
|
|
||||||
void encoder_update_user(uint8_t index, bool clockwise) {
|
|
||||||
if (index == 0) { /* First encoder */
|
|
||||||
if (clockwise) {
|
|
||||||
tap_code(KC_PGDN);
|
|
||||||
} else {
|
|
||||||
tap_code(KC_PGUP);
|
|
||||||
}
|
|
||||||
} else if (index == 1) { /* Second encoder
|
|
||||||
if (clockwise) {
|
|
||||||
tap_code(KC_UP);
|
|
||||||
} else {
|
|
||||||
tap_code(KC_DOWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Hardware
|
|
||||||
|
|
||||||
The A an B lines of the encoders should be wired directly to the MCU, and the C/common lines should be wired to ground.
|
|
@ -1,32 +0,0 @@
|
|||||||
# Grave Escape
|
|
||||||
|
|
||||||
If you're using a 60% keyboard, or any other layout with no F-row, you will have noticed that there is no dedicated Escape key. Grave Escape is a feature that allows you to share the grave key (<code>`</code> and `~`) with Escape.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Replace the `KC_GRAVE` key in your keymap (usually to the left of the `1` key) with `KC_GESC`. Most of the time this key will output `KC_ESC` when pressed. However, when Shift or GUI are held down it will output `KC_GRV` instead.
|
|
||||||
|
|
||||||
## What Your OS Sees
|
|
||||||
|
|
||||||
If Mary presses GESC on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses GESC it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>`</code> character.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|---------|-----------|------------------------------------------------------------------|
|
|
||||||
|`KC_GESC`|`GRAVE_ESC`|Escape when pressed, <code>`</code> when Shift or GUI are held|
|
|
||||||
|
|
||||||
### Caveats
|
|
||||||
|
|
||||||
On macOS, Command+<code>`</code> is by default mapped to "Move focus to next window" so it will not output a backtick. Additionally, Terminal always recognises this shortcut to cycle between windows, even if the shortcut is changed in the Keyboard preferences.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
There are several possible key combinations this will break, among them Control+Shift+Escape on Windows and Command+Option+Escape on macOS. To work around this, you can `#define` these options in your `config.h`:
|
|
||||||
|
|
||||||
|Define |Description |
|
|
||||||
|--------------------------|-----------------------------------------|
|
|
||||||
|`GRAVE_ESC_ALT_OVERRIDE` |Always send Escape if Alt is pressed |
|
|
||||||
|`GRAVE_ESC_CTRL_OVERRIDE` |Always send Escape if Control is pressed |
|
|
||||||
|`GRAVE_ESC_GUI_OVERRIDE` |Always send Escape if GUI is pressed |
|
|
||||||
|`GRAVE_ESC_SHIFT_OVERRIDE`|Always send Escape if Shift is pressed |
|
|
@ -1,147 +0,0 @@
|
|||||||
# Haptic Feedback
|
|
||||||
|
|
||||||
## Haptic feedback rules.mk options
|
|
||||||
|
|
||||||
The following options are currently available for haptic feedback in `rule.mk`:
|
|
||||||
|
|
||||||
`HAPTIC_ENABLE += DRV2605L`
|
|
||||||
|
|
||||||
`HAPTIC_ENABLE += SOLENOID`
|
|
||||||
|
|
||||||
## Known Supported Hardware
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
|--------------------|-------------------------------------------------|
|
|
||||||
| [LV061228B-L65-A](https://www.digikey.com/product-detail/en/jinlong-machinery-electronics-inc/LV061228B-L65-A/1670-1050-ND/7732325) | z-axis 2v LRA |
|
|
||||||
| [Mini Motor Disc](https://www.adafruit.com/product/1201) | small 2-5v ERM |
|
|
||||||
|
|
||||||
## Haptic Keycodes
|
|
||||||
|
|
||||||
Not all keycodes below will work depending on which haptic mechanism you have chosen.
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
|-----------|-------------------------------------------------------|
|
|
||||||
|`HPT_ON` | Turn haptic feedback on |
|
|
||||||
|`HPT_OFF` | Turn haptic feedback on |
|
|
||||||
|`HPT_TOG` | Toggle haptic feedback on/off |
|
|
||||||
|`HPT_RST` | Reset haptic feedback config to default |
|
|
||||||
|`HPT_FBK` | Toggle feedback to occur on keypress, release or both |
|
|
||||||
|`HPT_BUZ` | Toggle solenoid buzz on/off |
|
|
||||||
|`HPT_MODI` | Go to next DRV2605L waveform |
|
|
||||||
|`HPT_MODD` | Go to previous DRV2605L waveform |
|
|
||||||
|`HPT_DWLI` | Increase Solenoid dwell time |
|
|
||||||
|`HPT_DWLD` | Decrease Solenoid dwell time |
|
|
||||||
|
|
||||||
### Solenoids
|
|
||||||
|
|
||||||
First you will need a build a circuit to drive the solenoid through a mosfet as most MCU will not be able to provide the current needed to drive the coil in the solenoid.
|
|
||||||
|
|
||||||
[Wiring diagram provided by Adafruit](https://playground.arduino.cc/uploads/Learning/solenoid_driver.pdf)
|
|
||||||
|
|
||||||
Select a pin that has PWM for the signal pin
|
|
||||||
|
|
||||||
```
|
|
||||||
#define SOLENOID_PIN *pin*
|
|
||||||
```
|
|
||||||
|
|
||||||
Beware that some pins may be powered during bootloader (ie. A13 on the STM32F303 chip) and will result in the solenoid kept in the on state through the whole flashing process. This may overheat and damage the solenoid. If you find that the pin the solenoid is connected to is triggering the solenoid during bootloader/DFU, select another pin.
|
|
||||||
|
|
||||||
### DRV2605L
|
|
||||||
|
|
||||||
DRV2605L is controlled over i2c protocol, and has to be connected to the SDA and SCL pins, these varies depending on the MCU in use.
|
|
||||||
|
|
||||||
#### Feedback motor setup
|
|
||||||
|
|
||||||
This driver supports 2 different feedback motors. Set the following in your `config.h` based on which motor you have selected.
|
|
||||||
|
|
||||||
##### ERM
|
|
||||||
|
|
||||||
Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.
|
|
||||||
|
|
||||||
```
|
|
||||||
#define FB_ERM_LRA 0
|
|
||||||
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
|
||||||
#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
|
||||||
|
|
||||||
/* Please refer to your datasheet for the optimal setting for your specific motor. */
|
|
||||||
#define RATED_VOLTAGE 3
|
|
||||||
#define V_PEAK 5
|
|
||||||
```
|
|
||||||
##### LRA
|
|
||||||
|
|
||||||
Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.
|
|
||||||
|
|
||||||
```
|
|
||||||
#define FB_ERM_LRA 1
|
|
||||||
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
|
|
||||||
#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
|
|
||||||
|
|
||||||
/* Please refer to your datasheet for the optimal setting for your specific motor. */
|
|
||||||
#define RATED_VOLTAGE 2
|
|
||||||
#define V_PEAK 2.8
|
|
||||||
#define V_RMS 2.0
|
|
||||||
#define V_PEAK 2.1
|
|
||||||
#define F_LRA 205 /* resonance freq */
|
|
||||||
```
|
|
||||||
|
|
||||||
#### DRV2605L waveform library
|
|
||||||
|
|
||||||
DRV2605L comes with preloaded library of various waveform sequences that can be called and played. If writing a macro, these waveforms can be played using `DRV_pulse(*sequence name or number*)`
|
|
||||||
|
|
||||||
List of waveform sequences from the datasheet:
|
|
||||||
|
|
||||||
|seq# | Sequence name |seq# | Sequence name |seq# |Sequence name |
|
|
||||||
|-----|---------------------|-----|-----------------------------------|-----|--------------------------------------|
|
|
||||||
| 1 | strong_click | 43 | lg_dblclick_med_60 | 85 | transition_rampup_med_smooth2 |
|
|
||||||
| 2 | strong_click_60 | 44 | lg_dblsharp_tick | 86 | transition_rampup_short_smooth1 |
|
|
||||||
| 3 | strong_click_30 | 45 | lg_dblsharp_tick_80 | 87 | transition_rampup_short_smooth2 |
|
|
||||||
| 4 | sharp_click | 46 | lg_dblsharp_tick_60 | 88 | transition_rampup_long_sharp1 |
|
|
||||||
| 5 | sharp_click_60 | 47 | buzz | 89 | transition_rampup_long_sharp2 |
|
|
||||||
| 6 | sharp_click_30 | 48 | buzz_80 | 90 | transition_rampup_med_sharp1 |
|
|
||||||
| 7 | soft_bump | 49 | buzz_60 | 91 | transition_rampup_med_sharp2 |
|
|
||||||
| 8 | soft_bump_60 | 50 | buzz_40 | 92 | transition_rampup_short_sharp1 |
|
|
||||||
| 9 | soft_bump_30 | 51 | buzz_20 | 93 | transition_rampup_short_sharp2 |
|
|
||||||
| 10 | dbl_click | 52 | pulsing_strong | 94 | transition_rampdown_long_smooth1_50 |
|
|
||||||
| 11 | dbl_click_60 | 53 | pulsing_strong_80 | 95 | transition_rampdown_long_smooth2_50 |
|
|
||||||
| 12 | trp_click | 54 | pulsing_medium | 96 | transition_rampdown_med_smooth1_50 |
|
|
||||||
| 13 | soft_fuzz | 55 | pulsing_medium_80 | 97 | transition_rampdown_med_smooth2_50 |
|
|
||||||
| 14 | strong_buzz | 56 | pulsing_sharp | 98 | transition_rampdown_short_smooth1_50 |
|
|
||||||
| 15 | alert_750ms | 57 | pulsing_sharp_80 | 99 | transition_rampdown_short_smooth2_50 |
|
|
||||||
| 16 | alert_1000ms | 58 | transition_click | 100 | transition_rampdown_long_sharp1_50 |
|
|
||||||
| 17 | strong_click1 | 59 | transition_click_80 | 101 | transition_rampdown_long_sharp2_50 |
|
|
||||||
| 18 | strong_click2_80 | 60 | transition_click_60 | 102 | transition_rampdown_med_sharp1_50 |
|
|
||||||
| 19 | strong_click3_60 | 61 | transition_click_40 | 103 | transition_rampdown_med_sharp2_50 |
|
|
||||||
| 20 | strong_click4_30 | 62 | transition_click_20 | 104 | transition_rampdown_short_sharp1_50 |
|
|
||||||
| 21 | medium_click1 | 63 | transition_click_10 | 105 | transition_rampdown_short_sharp2_50 |
|
|
||||||
| 22 | medium_click2_80 | 64 | transition_hum | 106 | transition_rampup_long_smooth1_50 |
|
|
||||||
| 23 | medium_click3_60 | 65 | transition_hum_80 | 107 | transition_rampup_long_smooth2_50 |
|
|
||||||
| 24 | sharp_tick1 | 66 | transition_hum_60 | 108 | transition_rampup_med_smooth1_50 |
|
|
||||||
| 25 | sharp_tick2_80 | 67 | transition_hum_40 | 109 | transition_rampup_med_smooth2_50 |
|
|
||||||
| 26 | sharp_tick3_60 | 68 | transition_hum_20 | 110 | transition_rampup_short_smooth1_50 |
|
|
||||||
| 27 | sh_dblclick_str | 69 | transition_hum_10 | 111 | transition_rampup_short_smooth2_50 |
|
|
||||||
| 28 | sh_dblclick_str_80 | 70 | transition_rampdown_long_smooth1 | 112 | transition_rampup_long_sharp1_50 |
|
|
||||||
| 29 | sh_dblclick_str_60 | 71 | transition_rampdown_long_smooth2 | 113 | transition_rampup_long_sharp2_50 |
|
|
||||||
| 30 | sh_dblclick_str_30 | 72 | transition_rampdown_med_smooth1 | 114 | transition_rampup_med_sharp1_50 |
|
|
||||||
| 31 | sh_dblclick_med | 73 | transition_rampdown_med_smooth2 | 115 | transition_rampup_med_sharp2_50 |
|
|
||||||
| 32 | sh_dblclick_med_80 | 74 | transition_rampdown_short_smooth1 | 116 | transition_rampup_short_sharp1_50 |
|
|
||||||
| 33 | sh_dblclick_med_60 | 75 | transition_rampdown_short_smooth2 | 117 | transition_rampup_short_sharp2_50 |
|
|
||||||
| 34 | sh_dblsharp_tick | 76 | transition_rampdown_long_sharp1 | 118 | long_buzz_for_programmatic_stopping |
|
|
||||||
| 35 | sh_dblsharp_tick_80 | 77 | transition_rampdown_long_sharp2 | 119 | smooth_hum1_50 |
|
|
||||||
| 36 | sh_dblsharp_tick_60 | 78 | transition_rampdown_med_sharp1 | 120 | smooth_hum2_40 |
|
|
||||||
| 37 | lg_dblclick_str | 79 | transition_rampdown_med_sharp2 | 121 | smooth_hum3_30 |
|
|
||||||
| 38 | lg_dblclick_str_80 | 80 | transition_rampdown_short_sharp1 | 122 | smooth_hum4_20 |
|
|
||||||
| 39 | lg_dblclick_str_60 | 81 | transition_rampdown_short_sharp2 | 123 | smooth_hum5_10 |
|
|
||||||
| 40 | lg_dblclick_str_30 | 82 | transition_rampup_long_smooth1 | | |
|
|
||||||
| 41 | lg_dblclick_med | 83 | transition_rampup_long_smooth2 | | |
|
|
||||||
| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
|
|
||||||
### Optional DRV2605L defines
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DRV_GREETING *sequence name or number*
|
|
||||||
```
|
|
||||||
If haptic feedback is enabled, the keyboard will vibrate to a specific sqeuence during startup. That can be selected using the following define:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DRV_MODE_DEFAULT *sequence name or number*
|
|
||||||
```
|
|
||||||
This will set what sequence HPT_RST will set as the active mode. If not defined, mode will be set to 1 when HPT_RST is pressed.
|
|
@ -1,56 +0,0 @@
|
|||||||
# HD44780 LCD Displays
|
|
||||||
|
|
||||||
This is an integration of Peter Fleury's LCD library. This page will explain the basics. [For in depth documentation visit his page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
|
|
||||||
|
|
||||||
You can enable support for HD44780 Displays by setting the `HD44780_ENABLE` flag in your keyboards `rules.mk` to yes. This will use about 400 KB of extra space.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
You will need to configure the pins used by your display and its number of lines and collumn in your keyboards `config.h`.
|
|
||||||
|
|
||||||
Uncomment the section labled HD44780 and change the parameters as needed.
|
|
||||||
````
|
|
||||||
/*
|
|
||||||
* HD44780 LCD Display Configuration
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LCD_LINES 2 //< number of visible lines of the display
|
|
||||||
#define LCD_DISP_LENGTH 16 //< visibles characters per line of the display
|
|
||||||
#define LCD_IO_MODE 1 //< 0: memory mapped mode, 1: IO port mode
|
|
||||||
#if LCD_IO_MODE
|
|
||||||
#define LCD_PORT PORTB //< port for the LCD lines
|
|
||||||
#define LCD_DATA0_PORT LCD_PORT //< port for 4bit data bit 0
|
|
||||||
#define LCD_DATA1_PORT LCD_PORT //< port for 4bit data bit 1
|
|
||||||
#define LCD_DATA2_PORT LCD_PORT //< port for 4bit data bit 2
|
|
||||||
#define LCD_DATA3_PORT LCD_PORT //< port for 4bit data bit 3
|
|
||||||
#define LCD_DATA0_PIN 4 //< pin for 4bit data bit 0
|
|
||||||
#define LCD_DATA1_PIN 5 //< pin for 4bit data bit 1
|
|
||||||
#define LCD_DATA2_PIN 6 //< pin for 4bit data bit 2
|
|
||||||
#define LCD_DATA3_PIN 7 //< pin for 4bit data bit 3
|
|
||||||
#define LCD_RS_PORT LCD_PORT //< port for RS line
|
|
||||||
#define LCD_RS_PIN 3 //< pin for RS line
|
|
||||||
#define LCD_RW_PORT LCD_PORT //< port for RW line
|
|
||||||
#define LCD_RW_PIN 2 //< pin for RW line
|
|
||||||
#define LCD_E_PORT LCD_PORT //< port for Enable line
|
|
||||||
#define LCD_E_PIN 1 //< pin for Enable line
|
|
||||||
#endif
|
|
||||||
````
|
|
||||||
|
|
||||||
Should you need to configure other properties you can copy them from `quantum/hd44780.h` and set them in your `config.h`
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
To initialize your display call lcd_init() with one of these parameters:
|
|
||||||
````
|
|
||||||
LCD_DISP_OFF : display off
|
|
||||||
LCD_DISP_ON : display on, cursor off
|
|
||||||
LCD_DISP_ON_CURSOR : display on, cursor on
|
|
||||||
LCD_DISP_ON_CURSOR_BLINK : display on, cursor on flashing
|
|
||||||
````
|
|
||||||
This is best done in your keyboards `matrix_init_kb` or your keymaps `matrix_init_user`.
|
|
||||||
It is advised to clear the display before use.
|
|
||||||
To do so call `lcd_clrsrc()`.
|
|
||||||
|
|
||||||
To now print something to your Display you first call `lcd_gotoxy(column, line)`. To go to the start of the first line you would call `lcd_gotoxy(0, 0)` and then print a string with `lcd_puts("example string")`.
|
|
||||||
|
|
||||||
There are more posible methods to control the display. [For in depth documentation please visit the linked page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
|
|
@ -1,22 +0,0 @@
|
|||||||
# Key Lock
|
|
||||||
|
|
||||||
Sometimes you may find yourself needing to hold down a specific key for a long period of time. Key Lock holds down the next key you press for you. Press it again, and it will be released.
|
|
||||||
|
|
||||||
Let's say you need to type in ALL CAPS for a few sentences. Hit `KC_LOCK`, and then Shift. Now, Shift will be considered held until you tap it again. You can think of Key Lock as Caps Lock, but supercharged.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Then pick a key in your keymap and assign it the keycode `KC_LOCK`.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Keycode |Description |
|
|
||||||
|---------|--------------------------------------------------------------|
|
|
||||||
|`KC_LOCK`|Hold down the next key pressed, until the key is pressed again|
|
|
||||||
|
|
||||||
## Caveats
|
|
||||||
|
|
||||||
Key Lock is only able to hold standard action keys and [One Shot modifier](quantum_keycodes.md#one-shot-keys) 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.
|
|
@ -1,109 +0,0 @@
|
|||||||
# Layouts: Using a Keymap with Multiple Keyboards
|
|
||||||
|
|
||||||
The `layouts/` folder contains different physical key layouts that can apply to different keyboards.
|
|
||||||
|
|
||||||
```
|
|
||||||
layouts/
|
|
||||||
+ default/
|
|
||||||
| + 60_ansi/
|
|
||||||
| | + readme.md
|
|
||||||
| | + layout.json
|
|
||||||
| | + a_good_keymap/
|
|
||||||
| | | + keymap.c
|
|
||||||
| | | + readme.md
|
|
||||||
| | | + config.h
|
|
||||||
| | | + rules.mk
|
|
||||||
| | + <keymap folder>/
|
|
||||||
| | + ...
|
|
||||||
| + <layout folder>/
|
|
||||||
+ community/
|
|
||||||
| + <layout folder>/
|
|
||||||
| + ...
|
|
||||||
```
|
|
||||||
|
|
||||||
The `layouts/default/` and `layouts/community/` are two examples of layout "repositories" - currently `default` will contain all of the information concerning the layout, and one default keymap named `default_<layout>`, for users to use as a reference. `community` contains all of the community keymaps, with the eventual goal of being split-off into a separate repo for users to clone into `layouts/`. QMK searches through all folders in `layouts/`, so it's possible to have multiple repositories here.
|
|
||||||
|
|
||||||
Each layout folder is named (`[a-z0-9_]`) after the physical aspects of the layout, in the most generic way possible, and contains a `readme.md` with the layout to be defined by the keyboard:
|
|
||||||
|
|
||||||
```md
|
|
||||||
# 60_ansi
|
|
||||||
|
|
||||||
LAYOUT_60_ansi
|
|
||||||
```
|
|
||||||
|
|
||||||
New names should try to stick to the standards set by existing layouts, and can be discussed in the PR/Issue.
|
|
||||||
|
|
||||||
## Supporting a Layout
|
|
||||||
|
|
||||||
For a keyboard to support a layout, the variable must be defined in it's `<keyboard>.h`, and match the number of arguments/keys (and preferably the physical layout):
|
|
||||||
|
|
||||||
#define LAYOUT_60_ansi KEYMAP_ANSI
|
|
||||||
|
|
||||||
The name of the layout must match this regex: `[a-z0-9_]+`
|
|
||||||
|
|
||||||
The folder name must be added to the keyboard's `rules.mk`:
|
|
||||||
|
|
||||||
LAYOUTS = 60_ansi
|
|
||||||
|
|
||||||
`LAYOUTS` can be set in any keyboard folder level's `rules.mk`:
|
|
||||||
|
|
||||||
LAYOUTS = 60_iso
|
|
||||||
|
|
||||||
but the `LAYOUT_<layout>` variable must be defined in `<folder>.h` as well.
|
|
||||||
|
|
||||||
## Building a Keymap
|
|
||||||
|
|
||||||
You should be able to build the keyboard keymap with a command in this format:
|
|
||||||
|
|
||||||
make <keyboard>:<layout>
|
|
||||||
|
|
||||||
### Conflicting layouts
|
|
||||||
When a keyboard supports multiple layout options,
|
|
||||||
|
|
||||||
LAYOUTS = ortho_4x4 ortho_4x12
|
|
||||||
|
|
||||||
And a layout exists for both options,
|
|
||||||
```
|
|
||||||
layouts/
|
|
||||||
+ community/
|
|
||||||
| + ortho_4x4/
|
|
||||||
| | + <layout>/
|
|
||||||
| | | + ...
|
|
||||||
| + ortho_4x12/
|
|
||||||
| | + <layout>/
|
|
||||||
| | | + ...
|
|
||||||
| + ...
|
|
||||||
```
|
|
||||||
|
|
||||||
The FORCE_LAYOUT argument can be used to specify which layout to build
|
|
||||||
|
|
||||||
make <keyboard>:<layout> FORCE_LAYOUT=ortho_4x4
|
|
||||||
make <keyboard>:<layout> FORCE_LAYOUT=ortho_4x12
|
|
||||||
|
|
||||||
## Tips for Making Layouts Keyboard-Agnostic
|
|
||||||
|
|
||||||
### Includes
|
|
||||||
|
|
||||||
Instead of using `#include "planck.h"`, you can use this line to include whatever `<keyboard>.h` (`<folder>.h` should not be included here) file that is being compiled:
|
|
||||||
|
|
||||||
#include QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
If you want to keep some keyboard-specific code, you can use these variables to escape it with an `#ifdef` statement:
|
|
||||||
|
|
||||||
* `KEYBOARD_<folder1>_<folder2>`
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifdef KEYBOARD_planck
|
|
||||||
#ifdef KEYBOARD_planck_rev4
|
|
||||||
planck_rev4_function();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the names are lowercase and match the folder/file names for the keyboard/revision exactly.
|
|
||||||
|
|
||||||
### Keymaps
|
|
||||||
|
|
||||||
In order to support both split and non-split keyboards with the same layout, you need to use the keyboard agnostic `LAYOUT_<layout name>` macro in your keymap. For instance, in order for a Let's Split and Planck to share the same layout file, you need to use `LAYOUT_ortho_4x12` instead of `LAYOUT_planck_grid` or just `{}` for a C array.
|
|
@ -1,146 +0,0 @@
|
|||||||
# The Leader Key: A New Kind of Modifier
|
|
||||||
|
|
||||||
If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.
|
|
||||||
|
|
||||||
That's what `KC_LEAD` does. Here's an example:
|
|
||||||
|
|
||||||
1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
|
|
||||||
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low. .
|
|
||||||
* By default, this timeout is how long after pressing `KC_LEAD` to complete your entire sequence. This may be very low for some people. So you may want to increase this timeout. Optionally, you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. This allows you to maintain a low value here, but still be able to use the longer sequences. To enable this option, add `#define LEADER_PER_KEY_TIMING` to your `config.h`.
|
|
||||||
3. Within your `matrix_scan_user` function, add something like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
LEADER_EXTERNS();
|
|
||||||
|
|
||||||
void matrix_scan_user(void) {
|
|
||||||
LEADER_DICTIONARY() {
|
|
||||||
leading = false;
|
|
||||||
leader_end();
|
|
||||||
|
|
||||||
SEQ_ONE_KEY(KC_F) {
|
|
||||||
// Anything you can do in a macro.
|
|
||||||
SEND_STRING("QMK is awesome.");
|
|
||||||
}
|
|
||||||
SEQ_TWO_KEYS(KC_D, KC_D) {
|
|
||||||
SEND_STRING(SS_LCTRL("a")SS_LCTRL("c"));
|
|
||||||
}
|
|
||||||
SEQ_THREE_KEYS(KC_D, KC_D, KC_S) {
|
|
||||||
SEND_STRING("https://start.duckduckgo.com"SS_TAP(X_ENTER));
|
|
||||||
}
|
|
||||||
SEQ_TWO_KEYS(KC_A, KC_S) {
|
|
||||||
register_code(KC_LGUI);
|
|
||||||
register_code(KC_S);
|
|
||||||
unregister_code(KC_S);
|
|
||||||
unregister_code(KC_LGUI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see, you have a few function. You can use `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS`, `SEQ_THREE_KEYS` up to `SEQ_FIVE_KEYS` for longer sequences.
|
|
||||||
|
|
||||||
Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously.
|
|
||||||
|
|
||||||
## Adding Leader Key Support in the `rules.mk`
|
|
||||||
|
|
||||||
To add support for Leader Key you simply need to add a single line to your keymap's `rules.mk`:
|
|
||||||
|
|
||||||
```make
|
|
||||||
LEADER_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
## Per Key Timing on Leader keys
|
|
||||||
|
|
||||||
Rather than relying on an incredibly high timeout for long leader key strings or those of us without 200wpm typing skills, we can enable per key timing to ensure that each key pressed provides us with more time to finish our stroke. This is incredibly helpful with leader key emulation of tap dance (read: multiple taps of the same key like C, C, C).
|
|
||||||
|
|
||||||
In order to enable this, place this in your `config.h`:
|
|
||||||
```c
|
|
||||||
#define LEADER_PER_KEY_TIMING
|
|
||||||
```
|
|
||||||
|
|
||||||
After this, it's recommended that you lower your `LEADER_TIMEOUT` to something less that 300ms.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define LEADER_TIMEOUT 250
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, something like this won't seem impossible to do without a 1000MS leader key timeout:
|
|
||||||
|
|
||||||
```c
|
|
||||||
SEQ_THREE_KEYS(KC_C, KC_C, KC_C) {
|
|
||||||
SEND_STRING("Per key timing is great!!!");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
The Leader Key feature has some additional customization to how the Leader Key feature works. It has two functions that can be called at certain parts of the process. Namely `leader_start()` and `leader_end()`.
|
|
||||||
|
|
||||||
The `leader_start()` function is called when you tap the `KC_LEAD` key, and the `leader_end()` function is called when either the leader sequence is completed, or the leader timeout is hit.
|
|
||||||
|
|
||||||
You can add these functions to your code (`keymap.c` usually) to add feedback to the Leader sequences (such as beeping or playing music).
|
|
||||||
|
|
||||||
```c
|
|
||||||
void leader_start(void) {
|
|
||||||
// sequence started
|
|
||||||
}
|
|
||||||
|
|
||||||
void leader_end(void) {
|
|
||||||
// sequence ended (no success/failuer detection)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
This example will play the Mario "One Up" sound when you hit `KC_LEAD` to start the Leader Sequence, and will play "All Star" if it completes successfully or "Rick Roll" you if it fails.
|
|
||||||
|
|
||||||
```c
|
|
||||||
bool did_leader_succeed;
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
float leader_start[][2] = SONG(ONE_UP_SOUND );
|
|
||||||
float leader_succeed[][2] = SONG(ALL_STAR);
|
|
||||||
float leader_fail[][2] = SONG(RICK_ROLL);
|
|
||||||
#endif
|
|
||||||
LEADER_EXTERNS();
|
|
||||||
|
|
||||||
void matrix_scan_user(void) {
|
|
||||||
LEADER_DICTIONARY() {
|
|
||||||
did_leader_succeed = leading = false;
|
|
||||||
|
|
||||||
SEQ_ONE_KEY(KC_E) {
|
|
||||||
// Anything you can do in a macro.
|
|
||||||
SEND_STRING(SS_LCTRL(SS_LSFT("t")));
|
|
||||||
did_leader_succeed = true;
|
|
||||||
} else
|
|
||||||
SEQ_TWO_KEYS(KC_E, KC_D) {
|
|
||||||
SEND_STRING(SS_LGUI("r")"cmd"SS_TAP(KC_ENTER)SS_LCTRL("c"));
|
|
||||||
did_leader_succeed = true;
|
|
||||||
}
|
|
||||||
leader_end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void leader_start(void) {
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
PLAY_SONG(leader_start);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void leader_end(void) {
|
|
||||||
if (did_leader_succeed) {
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
PLAY_SONG(leader_succeed);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
#ifdef AUDIO_ENABLE
|
|
||||||
PLAY_SONG(leader_fail);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,90 +0,0 @@
|
|||||||
# LED Matrix Lighting
|
|
||||||
|
|
||||||
This feature allows you to use LED matrices driven by external drivers. It hooks into the backlight system so you can use the same keycodes as backlighting to control it.
|
|
||||||
|
|
||||||
If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_rgb_matrix.md) instead.
|
|
||||||
|
|
||||||
## Driver configuration
|
|
||||||
|
|
||||||
### IS31FL3731
|
|
||||||
|
|
||||||
There is basic support for addressable LED matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
|
|
||||||
|
|
||||||
LED_MATRIX_ENABLE = IS31FL3731
|
|
||||||
|
|
||||||
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
|
|
||||||
|
|
||||||
| Variable | Description | Default |
|
|
||||||
|----------|-------------|---------|
|
|
||||||
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages | 100 |
|
|
||||||
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
|
||||||
| `LED_DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
|
|
||||||
| `LED_DRIVER_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
|
|
||||||
| `LED_DRIVER_ADDR_1` | (Required) Address for the first LED driver | |
|
|
||||||
| `LED_DRIVER_ADDR_2` | (Optional) Address for the second LED driver | |
|
|
||||||
| `LED_DRIVER_ADDR_3` | (Optional) Address for the third LED driver | |
|
|
||||||
| `LED_DRIVER_ADDR_4` | (Optional) Address for the fourth LED driver | |
|
|
||||||
|
|
||||||
Here is an example using 2 drivers.
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
// 0b1110100 AD <-> GND
|
|
||||||
// 0b1110111 AD <-> VCC
|
|
||||||
// 0b1110101 AD <-> SCL
|
|
||||||
// 0b1110110 AD <-> SDA
|
|
||||||
#define LED_DRIVER_ADDR_1 0b1110100
|
|
||||||
#define LED_DRIVER_ADDR_2 0b1110110
|
|
||||||
|
|
||||||
#define LED_DRIVER_COUNT 2
|
|
||||||
#define LED_DRIVER_1_LED_COUNT 25
|
|
||||||
#define LED_DRIVER_2_LED_COUNT 24
|
|
||||||
#define LED_DRIVER_LED_COUNT LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL
|
|
||||||
|
|
||||||
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
|
|
||||||
|
|
||||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
|
||||||
|
|
||||||
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
|
|
||||||
/* Refer to IS31 manual for these locations
|
|
||||||
* driver
|
|
||||||
* | LED address
|
|
||||||
* | | */
|
|
||||||
{0, C3_3},
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
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-simple.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ).
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
All LED matrix keycodes are currently shared with the [backlight system](feature_backlight.md).
|
|
||||||
|
|
||||||
## LED Matrix Effects
|
|
||||||
|
|
||||||
Currently no LED matrix effects have been created.
|
|
||||||
|
|
||||||
## Custom layer effects
|
|
||||||
|
|
||||||
Custom layer effects can be done by defining this in your `<keyboard>.c`:
|
|
||||||
|
|
||||||
void led_matrix_indicators_kb(void) {
|
|
||||||
led_matrix_set_index_value(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
A similar function works in the keymap as `led_matrix_indicators_user`.
|
|
||||||
|
|
||||||
## Suspended state
|
|
||||||
|
|
||||||
To use the suspend feature, add this to your `<keyboard>.c`:
|
|
||||||
|
|
||||||
void suspend_power_down_kb(void)
|
|
||||||
{
|
|
||||||
led_matrix_set_suspend_state(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void suspend_wakeup_init_kb(void)
|
|
||||||
{
|
|
||||||
led_matrix_set_suspend_state(false);
|
|
||||||
}
|
|
@ -1,294 +0,0 @@
|
|||||||
# Macros
|
|
||||||
|
|
||||||
Macros allow you to send multiple keystrokes when pressing just one key. QMK has a number of ways to define and use macros. These can do anything you want: type common phrases for you, copypasta, repetitive game movements, or even help you code.
|
|
||||||
|
|
||||||
!> **Security Note**: While it is possible to use macros to send passwords, credit card numbers, and other sensitive information it is a supremely bad idea to do so. Anyone who gets a hold of your keyboard will be able to access that information by opening a text editor.
|
|
||||||
|
|
||||||
## The New Way: `SEND_STRING()` & `process_record_user`
|
|
||||||
|
|
||||||
Sometimes you just want a key to type out words or phrases. For the most common situations we've provided `SEND_STRING()`, which will type out your string (i.e. a sequence of characters) for you. All ASCII characters that are easily translated to a keycode are supported (e.g. `\n\t`).
|
|
||||||
|
|
||||||
Here is an example `keymap.c` for a two-key keyboard:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum custom_keycodes {
|
|
||||||
QMKBEST = SAFE_RANGE,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case QMKBEST:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// when keycode QMKBEST is pressed
|
|
||||||
SEND_STRING("QMK is the best thing ever!");
|
|
||||||
} else {
|
|
||||||
// when keycode QMKBEST is released
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = {
|
|
||||||
{QMKBEST, KC_ESC}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
What happens here is this:
|
|
||||||
We first define a new custom keycode in the range not occupied by any other keycodes.
|
|
||||||
Then we use the `process_record_user` function, which is called whenever a key is pressed or released, to check if our custom keycode has been activated.
|
|
||||||
If yes, we send the string `"QMK is the best thing ever!"` to the computer via the `SEND_STRING` macro (this is a C preprocessor macro, not to be confused with QMK macros).
|
|
||||||
We return `true` to indicate to the caller that the key press we just processed should continue to be processed as normal (as we didn't replace or alter the functionality).
|
|
||||||
Finally, we define the keymap so that the first button activates our macro and the second button is just an escape button.
|
|
||||||
|
|
||||||
You might want to add more than one macro.
|
|
||||||
You can do that by adding another keycode and adding another case to the switch statement, like so:
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum custom_keycodes {
|
|
||||||
QMKBEST = SAFE_RANGE,
|
|
||||||
QMKURL,
|
|
||||||
MY_OTHER_MACRO
|
|
||||||
};
|
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case QMKBEST:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// when keycode QMKBEST is pressed
|
|
||||||
SEND_STRING("QMK is the best thing ever!");
|
|
||||||
} else {
|
|
||||||
// when keycode QMKBEST is released
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QMKURL:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// when keycode QMKURL is pressed
|
|
||||||
SEND_STRING("https://qmk.fm/" SS_TAP(X_ENTER));
|
|
||||||
} else {
|
|
||||||
// when keycode QMKURL is released
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MY_OTHER_MACRO:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
SEND_STRING(SS_LCTRL("ac")); // selects all and copies
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = {
|
|
||||||
{MY_CUSTOM_MACRO, MY_OTHER_MACRO}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### TAP, DOWN and UP
|
|
||||||
|
|
||||||
You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`.
|
|
||||||
You can send arbitrary keycodes by wrapping them in:
|
|
||||||
|
|
||||||
* `SS_TAP()` presses and releases a key.
|
|
||||||
* `SS_DOWN()` presses (but does not release) a key.
|
|
||||||
* `SS_UP()` releases a key.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
SEND_STRING(SS_TAP(X_HOME));
|
|
||||||
|
|
||||||
Would tap `KC_HOME` - note how the prefix is now `X_`, and not `KC_`. You can also combine this with other strings, like this:
|
|
||||||
|
|
||||||
SEND_STRING("VE"SS_TAP(X_HOME)"LO");
|
|
||||||
|
|
||||||
Which would send "VE" followed by a `KC_HOME` tap, and "LO" (spelling "LOVE" if on a newline).
|
|
||||||
|
|
||||||
There's also a couple of mod shortcuts you can use:
|
|
||||||
|
|
||||||
* `SS_LCTRL(string)`
|
|
||||||
* `SS_LGUI(string)`
|
|
||||||
* `SS_LALT(string)`
|
|
||||||
* `SS_LSFT(string)`
|
|
||||||
* `SS_RALT(string)`
|
|
||||||
|
|
||||||
These press the respective modifier, send the supplied string and then release the modifier.
|
|
||||||
They can be used like this:
|
|
||||||
|
|
||||||
SEND_STRING(SS_LCTRL("a"));
|
|
||||||
|
|
||||||
Which would send LCTRL+a (LCTRL down, a, LCTRL up) - notice that they take strings (eg `"k"`), and not the `X_K` keycodes.
|
|
||||||
|
|
||||||
### Alternative Keymaps
|
|
||||||
|
|
||||||
By default, it assumes a US keymap with a QWERTY layout; if you want to change that (e.g. if your OS uses software Colemak), include this somewhere in your keymap:
|
|
||||||
|
|
||||||
#include <sendstring_colemak.h>
|
|
||||||
|
|
||||||
### Strings in Memory
|
|
||||||
|
|
||||||
If for some reason you're manipulating strings and need to print out something you just generated (instead of being a literal, constant string), you can use `send_string()`, like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
char my_str[4] = "ok.";
|
|
||||||
send_string(my_str);
|
|
||||||
```
|
|
||||||
|
|
||||||
The shortcuts defined above won't work with `send_string()`, but you can separate things out to different lines if needed:
|
|
||||||
|
|
||||||
```c
|
|
||||||
char my_str[4] = "ok.";
|
|
||||||
SEND_STRING("I said: ");
|
|
||||||
send_string(my_str);
|
|
||||||
SEND_STRING(".."SS_TAP(X_END));
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Advanced Macro Functions
|
|
||||||
|
|
||||||
There are some functions you may find useful in macro-writing. Keep in mind that while you can write some fairly advanced code within a macro, if your functionality gets too complex you may want to define a custom keycode instead. Macros are meant to be simple.
|
|
||||||
|
|
||||||
### `record->event.pressed`
|
|
||||||
|
|
||||||
This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is
|
|
||||||
|
|
||||||
```c
|
|
||||||
if (record->event.pressed) {
|
|
||||||
// on keydown
|
|
||||||
} else {
|
|
||||||
// on keyup
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `register_code(<kc>);`
|
|
||||||
|
|
||||||
This sends the `<kc>` keydown event to the computer. Some examples would be `KC_ESC`, `KC_C`, `KC_4`, and even modifiers such as `KC_LSFT` and `KC_LGUI`.
|
|
||||||
|
|
||||||
### `unregister_code(<kc>);`
|
|
||||||
|
|
||||||
Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent.
|
|
||||||
|
|
||||||
### `tap_code(<kc>);`
|
|
||||||
|
|
||||||
This will send `register_code(<kc>)` and then `unregister_code(<kc>)`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it).
|
|
||||||
|
|
||||||
If you're having issues with taps (un)registering, you can add a delay between the register and unregister events by setting `#define TAP_CODE_DELAY 100` in your `config.h` file. The value is in milliseconds.
|
|
||||||
|
|
||||||
### `register_code16(<kc>);`, `unregister_code16(<kc>);` and `tap_code16(<kc>);`
|
|
||||||
|
|
||||||
These functions work similar to their regular counterparts, but allow you to use modded keycodes (with Shift, Alt, Control, and/or GUI applied to them).
|
|
||||||
|
|
||||||
Eg, you could use `register_code16(S(KC_5));` instead of registering the mod, then registering the keycode.
|
|
||||||
|
|
||||||
### `clear_keyboard();`
|
|
||||||
|
|
||||||
This will clear all mods and keys currently pressed.
|
|
||||||
|
|
||||||
### `clear_mods();`
|
|
||||||
|
|
||||||
This will clear all mods currently pressed.
|
|
||||||
|
|
||||||
### `clear_keyboard_but_mods();`
|
|
||||||
|
|
||||||
This will clear all keys besides the mods currently pressed.
|
|
||||||
|
|
||||||
|
|
||||||
## **(DEPRECATED)** The Old Way: `MACRO()` & `action_get_macro`
|
|
||||||
|
|
||||||
!> This is inherited from TMK, and hasn't been updated - it's recommended that you use `SEND_STRING` and `process_record_user` instead.
|
|
||||||
|
|
||||||
By default QMK assumes you don't have any macros. To define your macros you create an `action_get_macro()` function. For example:
|
|
||||||
|
|
||||||
```c
|
|
||||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
|
||||||
if (record->event.pressed) {
|
|
||||||
switch(id) {
|
|
||||||
case 0:
|
|
||||||
return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END);
|
|
||||||
case 1:
|
|
||||||
return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MACRO_NONE;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
This defines two macros which will be run when the key they are assigned to is pressed. If instead you'd like them to run when the key is released you can change the if statement:
|
|
||||||
|
|
||||||
if (!record->event.pressed) {
|
|
||||||
|
|
||||||
### Macro Commands
|
|
||||||
|
|
||||||
A macro can include the following commands:
|
|
||||||
|
|
||||||
* I() change interval of stroke in milliseconds.
|
|
||||||
* D() press key.
|
|
||||||
* U() release key.
|
|
||||||
* T() type key(press and release).
|
|
||||||
* W() wait (milliseconds).
|
|
||||||
* END end mark.
|
|
||||||
|
|
||||||
### Mapping a Macro to a Key
|
|
||||||
|
|
||||||
Use the `M()` function within your keymap to call a macro. For example, here is the keymap for a 2-key keyboard:
|
|
||||||
|
|
||||||
```c
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT(
|
|
||||||
M(0), M(1)
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
|
||||||
if (record->event.pressed) {
|
|
||||||
switch(id) {
|
|
||||||
case 0:
|
|
||||||
return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END);
|
|
||||||
case 1:
|
|
||||||
return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MACRO_NONE;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
When you press the key on the left it will type "Hi!" and when you press the key on the right it will type "Bye!".
|
|
||||||
|
|
||||||
### Naming Your Macros
|
|
||||||
|
|
||||||
If you have a bunch of macros you want to refer to from your keymap while keeping the keymap easily readable you can name them using `#define` at the top of your file.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define M_HI M(0)
|
|
||||||
#define M_BYE M(1)
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT(
|
|
||||||
M_HI, M_BYE
|
|
||||||
),
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Advanced Example: Single-Key Copy/Paste
|
|
||||||
|
|
||||||
This example defines a macro which sends `Ctrl-C` when pressed down, and `Ctrl-V` when released.
|
|
||||||
|
|
||||||
```c
|
|
||||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
|
||||||
switch(id) {
|
|
||||||
case 0: {
|
|
||||||
if (record->event.pressed) {
|
|
||||||
return MACRO( D(LCTL), T(C), U(LCTL), END );
|
|
||||||
} else {
|
|
||||||
return MACRO( D(LCTL), T(V), U(LCTL), END );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MACRO_NONE;
|
|
||||||
};
|
|
||||||
```
|
|
@ -1,114 +0,0 @@
|
|||||||
# Mousekeys
|
|
||||||
|
|
||||||
|
|
||||||
Mousekeys is a feature that allows you to emulate a mouse using your keyboard. You can move the pointer around, click up to 5 buttons, and even scroll in all 4 directions.
|
|
||||||
|
|
||||||
There are 2 ways to define how the mousekeys behave, using "[auto-accelerating](#configuring-the-behavior-of-mousekeys-with-auto-accelerated-movement)" or "[3-speed constant](#configuring-the-behavior-of-mousekeys-with-3-speed-constant-movement)" behavior.
|
|
||||||
|
|
||||||
In either case, you will need to enable mousekeys in your makefile,
|
|
||||||
and add the relevant [keycodes](#mapping-mouse-actions-to-keyboard-keys) to your keymap.
|
|
||||||
|
|
||||||
#### Enable Mousekeys
|
|
||||||
|
|
||||||
To enable the mousekey functionality, add the following line to your keymap's `rules.mk`:
|
|
||||||
|
|
||||||
```
|
|
||||||
MOUSEKEY_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Mapping Mouse Actions to Keyboard Keys
|
|
||||||
|
|
||||||
You can use these keycodes within your keymap to map button presses to mouse actions:
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------|---------|-----------------------------------|
|
|
||||||
|`KC_MS_UP` |`KC_MS_U`|Mouse Cursor Up |
|
|
||||||
|`KC_MS_DOWN` |`KC_MS_D`|Mouse Cursor Down |
|
|
||||||
|`KC_MS_LEFT` |`KC_MS_L`|Mouse Cursor Left |
|
|
||||||
|`KC_MS_RIGHT` |`KC_MS_R`|Mouse Cursor Right |
|
|
||||||
|`KC_MS_BTN1` |`KC_BTN1`|Mouse Button 1 |
|
|
||||||
|`KC_MS_BTN2` |`KC_BTN2`|Mouse Button 2 |
|
|
||||||
|`KC_MS_BTN3` |`KC_BTN3`|Mouse Button 3 |
|
|
||||||
|`KC_MS_BTN4` |`KC_BTN4`|Mouse Button 4 |
|
|
||||||
|`KC_MS_BTN5` |`KC_BTN5`|Mouse Button 5 |
|
|
||||||
|`KC_MS_WH_UP` |`KC_WH_U`|Mouse Wheel Up |
|
|
||||||
|`KC_MS_WH_DOWN` |`KC_WH_D`|Mouse Wheel Down |
|
|
||||||
|`KC_MS_WH_LEFT` |`KC_WH_L`|Mouse Wheel Left |
|
|
||||||
|`KC_MS_WH_RIGHT`|`KC_WH_R`|Mouse Wheel Right |
|
|
||||||
|`KC_MS_ACCEL0` |`KC_ACL0`|Set mouse acceleration to 0(slow) |
|
|
||||||
|`KC_MS_ACCEL1` |`KC_ACL1`|Set mouse acceleration to 1(medium)|
|
|
||||||
|`KC_MS_ACCEL2` |`KC_ACL2`|Set mouse acceleration to 2(fast) |
|
|
||||||
|
|
||||||
|
|
||||||
## Configuring the Behavior of Mousekeys with auto-accelerated movement
|
|
||||||
|
|
||||||
This behavior is intended to emulate the X Window System MouseKeysAccel feature. You can read more about it [on Wikipedia](https://en.wikipedia.org/wiki/Mouse_keys).
|
|
||||||
|
|
||||||
The default speed for controlling the mouse with the keyboard is intentionally slow. You can adjust these parameters by adding these settings to your keymap's `config.h` file. All times are specified in milliseconds (ms).
|
|
||||||
|
|
||||||
```
|
|
||||||
#define MOUSEKEY_DELAY 300
|
|
||||||
#define MOUSEKEY_INTERVAL 50
|
|
||||||
#define MOUSEKEY_MAX_SPEED 10
|
|
||||||
#define MOUSEKEY_TIME_TO_MAX 20
|
|
||||||
#define MOUSEKEY_WHEEL_MAX_SPEED 8
|
|
||||||
#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `MOUSEKEY_DELAY`
|
|
||||||
|
|
||||||
When one of the mouse movement buttons is pressed this setting is used to define the delay between that button press and the mouse cursor moving. Some people find that small movements are impossible if this setting is too low, while settings that are too high feel sluggish.
|
|
||||||
|
|
||||||
#### `MOUSEKEY_INTERVAL`
|
|
||||||
|
|
||||||
When a movement key is held down this specifies how long to wait between each movement report. Lower settings will translate into an effectively higher mouse speed.
|
|
||||||
|
|
||||||
#### `MOUSEKEY_MAX_SPEED`
|
|
||||||
|
|
||||||
As a movement key is held down the speed of the mouse cursor will increase until it reaches `MOUSEKEY_MAX_SPEED`.
|
|
||||||
|
|
||||||
#### `MOUSEKEY_TIME_TO_MAX`
|
|
||||||
|
|
||||||
How long you want to hold down a movement key for until `MOUSEKEY_MAX_SPEED` is reached. This controls how quickly your cursor will accelerate.
|
|
||||||
|
|
||||||
#### `MOUSEKEY_WHEEL_MAX_SPEED`
|
|
||||||
|
|
||||||
The top speed for scrolling movements.
|
|
||||||
|
|
||||||
#### `MOUSEKEY_WHEEL_TIME_TO_MAX`
|
|
||||||
|
|
||||||
How long you want to hold down a scroll key for until `MOUSEKEY_WHEEL_MAX_SPEED` is reached. This controls how quickly your scrolling will accelerate.
|
|
||||||
|
|
||||||
|
|
||||||
## Configuring the Behavior of Mousekeys with 3-speed constant movement
|
|
||||||
|
|
||||||
In your keymap's `config.h`, you must add the line:
|
|
||||||
```
|
|
||||||
#define MK_3_SPEED
|
|
||||||
```
|
|
||||||
Then you can precisely define 3 different speeds for both the cursor and the mouse wheel, and also whether speed selection is momentary or tap-to-select.
|
|
||||||
For each speed, you can specify how many milliseconds you want between reports(interval), and how far you want to it to move per report(offset).
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define MK_3_SPEED
|
|
||||||
#define MK_MOMENTARY_ACCEL // comment this out for tap-to-select acceleration
|
|
||||||
// cursor speeds:
|
|
||||||
#define MK_C_OFFSET_SLOW 1 // pixels
|
|
||||||
#define MK_C_INTERVAL_SLOW 100 // milliseconds
|
|
||||||
#define MK_C_OFFSET_MED 4
|
|
||||||
#define MK_C_INTERVAL_MED 16
|
|
||||||
#define MK_C_OFFSET_FAST 12
|
|
||||||
#define MK_C_INTERVAL_FAST 16
|
|
||||||
// scroll wheel speeds:
|
|
||||||
#define MK_W_OFFSET_SLOW 1 // wheel clicks
|
|
||||||
#define MK_W_INTERVAL_SLOW 400 // milliseconds
|
|
||||||
#define MK_W_OFFSET_MED 1
|
|
||||||
#define MK_W_INTERVAL_MED 200
|
|
||||||
#define MK_W_OFFSET_FAST 1
|
|
||||||
#define MK_W_INTERVAL_FAST 100
|
|
||||||
```
|
|
||||||
|
|
||||||
Medium values will be used as the default or unmodified speed.
|
|
||||||
The speed at which both the cursor and scrolling move can be selected with KC_ACL0, KC_ACL1, KC_ACL2 for slow, medium, and fast. However, if you leave MK_MOMENTARY_ACCEL defined then there is no need to ever send KC_ACL1, since that will be the unmodified speed.
|
|
@ -1,47 +0,0 @@
|
|||||||
## 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:
|
|
||||||
|
|
||||||
```
|
|
||||||
POINTING_DEVICE_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
To manipulate the mouse report, you can use the following functions:
|
|
||||||
|
|
||||||
* `pointing_device_get_report()` - Returns the current report_mouse_t that represents the information sent to the host computer
|
|
||||||
* `pointing_device_set_report(report_mouse_t newMouseReport)` - Overrides and saves the report_mouse_t to be sent to the host computer
|
|
||||||
|
|
||||||
Keep in mind that a report_mouse_t (here "mouseReport") has the following properties:
|
|
||||||
|
|
||||||
* `mouseReport.x` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ to the right, - to the left) on the x axis.
|
|
||||||
* `mouseReport.y` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ upward, - downward) on the y axis.
|
|
||||||
* `mouseReport.v` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing vertical scrolling (+ upward, - downward).
|
|
||||||
* `mouseReport.h` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing horizontal scrolling (+ right, - left).
|
|
||||||
* `mouseReport.buttons` - this is a uint8_t in which the last 5 bits are used. These bits represent the mouse button state - bit 3 is mouse button 5, and bit 7 is mouse button 1.
|
|
||||||
|
|
||||||
When the mouse report is sent, the x, y, v, and h values are set to 0 (this is done in "pointing_device_send()", which can be overridden to avoid this behavior). This way, button states persist, but movement will only occur once. For further customization, both `pointing_device_init` and `pointing_device_task` can be overridden.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
```
|
|
||||||
case MS_SPECIAL:
|
|
||||||
report_mouse_t currentReport = pointing_device_get_report();
|
|
||||||
if (record->event.pressed)
|
|
||||||
{
|
|
||||||
currentReport.v = 127;
|
|
||||||
currentReport.h = 127;
|
|
||||||
currentReport.buttons |= MOUSE_BTN1; //this is defined in report.h
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentReport.v = -127;
|
|
||||||
currentReport.h = -127;
|
|
||||||
currentReport.buttons &= ~MOUSE_BTN1;
|
|
||||||
}
|
|
||||||
pointing_device_set_report(currentReport);
|
|
||||||
break;
|
|
||||||
```
|
|
||||||
|
|
||||||
Recall that the mouse report is set to zero (except the buttons) whenever it is sent, so the scrolling would only occur once in each case.
|
|
@ -1,276 +0,0 @@
|
|||||||
## PS/2 Mouse Support
|
|
||||||
|
|
||||||
Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device.
|
|
||||||
|
|
||||||
To hook up a Trackpoint, you need to obtain a Trackpoint module (i.e. harvest from a Thinkpad keyboard), identify the function of each pin of the module, and make the necessary circuitry between controller and Trackpoint module. For more information, please refer to [Trackpoint Hardware](https://deskthority.net/wiki/TrackPoint_Hardware) page on Deskthority Wiki.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
To get the things working, a 4.7K drag is needed between the two lines DATA and CLK and the line 5+.
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
DATA ----------+--------- PIN
|
|
||||||
|
|
|
||||||
4.7K
|
|
||||||
|
|
|
||||||
MODULE 5+ --------+--+--------- PWR CONTROLLER
|
|
||||||
|
|
|
||||||
4.7K
|
|
||||||
|
|
|
||||||
CLK ------+------------ PIN
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### 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:
|
|
||||||
|
|
||||||
```
|
|
||||||
PS2_MOUSE_ENABLE = yes
|
|
||||||
PS2_USE_BUSYWAIT = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
In your keyboard config.h:
|
|
||||||
|
|
||||||
```
|
|
||||||
#ifdef PS2_USE_BUSYWAIT
|
|
||||||
# define PS2_CLOCK_PORT PORTD
|
|
||||||
# define PS2_CLOCK_PIN PIND
|
|
||||||
# define PS2_CLOCK_DDR DDRD
|
|
||||||
# define PS2_CLOCK_BIT 1
|
|
||||||
# define PS2_DATA_PORT PORTD
|
|
||||||
# define PS2_DATA_PIN PIND
|
|
||||||
# define PS2_DATA_DDR DDRD
|
|
||||||
# define PS2_DATA_BIT 2
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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:
|
|
||||||
|
|
||||||
```
|
|
||||||
PS2_MOUSE_ENABLE = yes
|
|
||||||
PS2_USE_INT = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
In your keyboard config.h:
|
|
||||||
|
|
||||||
```
|
|
||||||
#ifdef PS2_USE_INT
|
|
||||||
#define PS2_CLOCK_PORT PORTD
|
|
||||||
#define PS2_CLOCK_PIN PIND
|
|
||||||
#define PS2_CLOCK_DDR DDRD
|
|
||||||
#define PS2_CLOCK_BIT 2
|
|
||||||
#define PS2_DATA_PORT PORTD
|
|
||||||
#define PS2_DATA_PIN PIND
|
|
||||||
#define PS2_DATA_DDR DDRD
|
|
||||||
#define PS2_DATA_BIT 5
|
|
||||||
|
|
||||||
#define PS2_INT_INIT() do { \
|
|
||||||
EICRA |= ((1<<ISC21) | \
|
|
||||||
(0<<ISC20)); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_INT_ON() do { \
|
|
||||||
EIMSK |= (1<<INT2); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_INT_OFF() do { \
|
|
||||||
EIMSK &= ~(1<<INT2); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_INT_VECT INT2_vect
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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:
|
|
||||||
|
|
||||||
```
|
|
||||||
PS2_MOUSE_ENABLE = yes
|
|
||||||
PS2_USE_USART = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
In your keyboard config.h:
|
|
||||||
|
|
||||||
```
|
|
||||||
#ifdef PS2_USE_USART
|
|
||||||
#define PS2_CLOCK_PORT PORTD
|
|
||||||
#define PS2_CLOCK_PIN PIND
|
|
||||||
#define PS2_CLOCK_DDR DDRD
|
|
||||||
#define PS2_CLOCK_BIT 5
|
|
||||||
#define PS2_DATA_PORT PORTD
|
|
||||||
#define PS2_DATA_PIN PIND
|
|
||||||
#define PS2_DATA_DDR DDRD
|
|
||||||
#define PS2_DATA_BIT 2
|
|
||||||
|
|
||||||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
|
|
||||||
/* set DDR of CLOCK as input to be slave */
|
|
||||||
#define PS2_USART_INIT() do { \
|
|
||||||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
|
|
||||||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
|
|
||||||
UCSR1C = ((1 << UMSEL10) | \
|
|
||||||
(3 << UPM10) | \
|
|
||||||
(0 << USBS1) | \
|
|
||||||
(3 << UCSZ10) | \
|
|
||||||
(0 << UCPOL1)); \
|
|
||||||
UCSR1A = 0; \
|
|
||||||
UBRR1H = 0; \
|
|
||||||
UBRR1L = 0; \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_USART_RX_INT_ON() do { \
|
|
||||||
UCSR1B = ((1 << RXCIE1) | \
|
|
||||||
(1 << RXEN1)); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_USART_RX_POLL_ON() do { \
|
|
||||||
UCSR1B = (1 << RXEN1); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_USART_OFF() do { \
|
|
||||||
UCSR1C = 0; \
|
|
||||||
UCSR1B &= ~((1 << RXEN1) | \
|
|
||||||
(1 << TXEN1)); \
|
|
||||||
} while (0)
|
|
||||||
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
|
|
||||||
#define PS2_USART_RX_DATA UDR1
|
|
||||||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
|
|
||||||
#define PS2_USART_RX_VECT USART1_RX_vect
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
||||||
### Additional Settings
|
|
||||||
|
|
||||||
#### PS/2 Mouse Features
|
|
||||||
|
|
||||||
These enable settings supported by the PS/2 mouse protocol: http://www.computer-engineering.org/ps2mouse/
|
|
||||||
|
|
||||||
```
|
|
||||||
/* Use remote mode instead of the default stream mode (see link) */
|
|
||||||
#define PS2_MOUSE_USE_REMOTE_MODE
|
|
||||||
|
|
||||||
/* Enable the scrollwheel or scroll gesture on your mouse or touchpad */
|
|
||||||
#define PS2_MOUSE_ENABLE_SCROLLING
|
|
||||||
|
|
||||||
/* Some mice will need a scroll mask to be configured. The default is 0xFF. */
|
|
||||||
#define PS2_MOUSE_SCROLL_MASK 0x0F
|
|
||||||
|
|
||||||
/* Applies a transformation to the movement before sending to the host (see link) */
|
|
||||||
#define PS2_MOUSE_USE_2_1_SCALING
|
|
||||||
|
|
||||||
/* The time to wait after initializing the ps2 host */
|
|
||||||
#define PS2_MOUSE_INIT_DELAY 1000 /* Default */
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also call the following functions from ps2_mouse.h
|
|
||||||
|
|
||||||
```
|
|
||||||
void ps2_mouse_disable_data_reporting(void);
|
|
||||||
|
|
||||||
void ps2_mouse_enable_data_reporting(void);
|
|
||||||
|
|
||||||
void ps2_mouse_set_remote_mode(void);
|
|
||||||
|
|
||||||
void ps2_mouse_set_stream_mode(void);
|
|
||||||
|
|
||||||
void ps2_mouse_set_scaling_2_1(void);
|
|
||||||
|
|
||||||
void ps2_mouse_set_scaling_1_1(void);
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_X_MULTIPLIER 3
|
|
||||||
#define PS2_MOUSE_Y_MULTIPLIER 3
|
|
||||||
#define PS2_MOUSE_V_MULTIPLIER 1
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Scroll Button
|
|
||||||
|
|
||||||
If you're using a trackpoint, you will likely want to be able to use it for scrolling.
|
|
||||||
Its 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:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BUTTON_MIDDLE) /* Default */
|
|
||||||
```
|
|
||||||
|
|
||||||
To disable the scroll button feature:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_SCROLL_BTN_MASK 0
|
|
||||||
```
|
|
||||||
|
|
||||||
The available buttons are:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_BTN_LEFT 0
|
|
||||||
#define PS2_MOUSE_BTN_RIGHT 1
|
|
||||||
#define PS2_MOUSE_BTN_MIDDLE 2
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also combine buttons in the mask by `|`ing them together.
|
|
||||||
|
|
||||||
Once you've configured your scroll button mask, you must configure the scroll button send interval.
|
|
||||||
This is the interval before which if the scroll buttons were released they would be sent to the host.
|
|
||||||
After this interval, they will cause the mouse to scroll and will not be sent.
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_SCROLL_BTN_SEND 300 /* Default */
|
|
||||||
```
|
|
||||||
|
|
||||||
To disable sending the scroll buttons:
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_SCROLL_BTN_SEND 0
|
|
||||||
```
|
|
||||||
|
|
||||||
Fine control over the scrolling is supported with the following defines:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_SCROLL_DIVISOR_H 2
|
|
||||||
#define PS2_MOUSE_SCROLL_DIVISOR_V 2
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Invert Mouse and Scroll Axes
|
|
||||||
|
|
||||||
To invert the X and Y axes you can put:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_INVERT_X
|
|
||||||
#define PS2_MOUSE_INVERT_Y
|
|
||||||
```
|
|
||||||
|
|
||||||
into config.h.
|
|
||||||
|
|
||||||
To reverse the scroll axes you can put:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define PS2_MOUSE_INVERT_H
|
|
||||||
#define PS2_MOUSE_INVERT_V
|
|
||||||
```
|
|
||||||
|
|
||||||
into config.h.
|
|
||||||
|
|
||||||
#### Debug Settings
|
|
||||||
|
|
||||||
To debug the mouse, add `debug_mouse = true` or enable via bootmagic.
|
|
||||||
|
|
||||||
```
|
|
||||||
/* To debug the mouse reports */
|
|
||||||
#define PS2_MOUSE_DEBUG_HID
|
|
||||||
#define PS2_MOUSE_DEBUG_RAW
|
|
||||||
```
|
|
@ -1,223 +0,0 @@
|
|||||||
# RGB Matrix Lighting
|
|
||||||
|
|
||||||
This feature allows you to use RGB LED matrices driven by external drivers. It hooks into the RGBLIGHT system so you can use the same keycodes as RGBLIGHT to control it.
|
|
||||||
|
|
||||||
If you want to use single color LED's you should use the [LED Matrix Subsystem](feature_led_matrix.md) instead.
|
|
||||||
|
|
||||||
## Driver configuration
|
|
||||||
|
|
||||||
### IS31FL3731
|
|
||||||
|
|
||||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
|
|
||||||
|
|
||||||
RGB_MATRIX_ENABLE = IS31FL3731
|
|
||||||
|
|
||||||
Configure the hardware via your `config.h`:
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
// 0b1110100 AD <-> GND
|
|
||||||
// 0b1110111 AD <-> VCC
|
|
||||||
// 0b1110101 AD <-> SCL
|
|
||||||
// 0b1110110 AD <-> SDA
|
|
||||||
#define DRIVER_ADDR_1 0b1110100
|
|
||||||
#define DRIVER_ADDR_2 0b1110110
|
|
||||||
|
|
||||||
#define DRIVER_COUNT 2
|
|
||||||
#define DRIVER_1_LED_TOTAL 25
|
|
||||||
#define DRIVER_2_LED_TOTAL 24
|
|
||||||
#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL
|
|
||||||
|
|
||||||
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
|
|
||||||
|
|
||||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
|
||||||
|
|
||||||
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
|
|
||||||
/* Refer to IS31 manual for these locations
|
|
||||||
* driver
|
|
||||||
* | R location
|
|
||||||
* | | G location
|
|
||||||
* | | | B location
|
|
||||||
* | | | | */
|
|
||||||
{0, C1_3, C2_3, C3_3},
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
|
|
||||||
|
|
||||||
RGB_MATRIX_ENABLE = IS31FL3733
|
|
||||||
|
|
||||||
Configure the hardware via your `config.h`:
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
// 00 <-> GND
|
|
||||||
// 01 <-> SCL
|
|
||||||
// 10 <-> SDA
|
|
||||||
// 11 <-> VCC
|
|
||||||
// ADDR1 represents A1:A0 of the 7-bit address.
|
|
||||||
// ADDR2 represents A3:A2 of the 7-bit address.
|
|
||||||
// The result is: 0b101(ADDR2)(ADDR1)
|
|
||||||
#define DRIVER_ADDR_1 0b1010000
|
|
||||||
#define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
|
|
||||||
|
|
||||||
#define DRIVER_COUNT 2
|
|
||||||
#define DRIVER_1_LED_TOTAL 64
|
|
||||||
#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
|
|
||||||
|
|
||||||
Currently only a single drivers is supported, but it would be trivial to support all 4 combinations. For now define `DRIVER_ADDR_2` as `DRIVER_ADDR_1`
|
|
||||||
|
|
||||||
Define these arrays listing all the LEDs in your `<keyboard>.c`:
|
|
||||||
|
|
||||||
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
|
|
||||||
/* Refer to IS31 manual for these locations
|
|
||||||
* driver
|
|
||||||
* | R location
|
|
||||||
* | | G location
|
|
||||||
* | | | B location
|
|
||||||
* | | | | */
|
|
||||||
{0, B_1, A_1, C_1},
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0` right now).
|
|
||||||
|
|
||||||
From this point forward the configuration is the same for all the drivers.
|
|
||||||
|
|
||||||
const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = {
|
|
||||||
/* {row | col << 4}
|
|
||||||
* | {x=0..224, y=0..64}
|
|
||||||
* | | modifier
|
|
||||||
* | | | */
|
|
||||||
{{0|(0<<4)}, {20.36*0, 21.33*0}, 1},
|
|
||||||
{{0|(1<<4)}, {20.36*1, 21.33*0}, 1},
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
The format for the matrix position used in this array is `{row | (col << 4)}`. The `x` is between (inclusive) 0-224, and `y` is between (inclusive) 0-64. The easiest way to calculate these positions is:
|
|
||||||
|
|
||||||
x = 224 / ( NUMBER_OF_COLS - 1 ) * ROW_POSITION
|
|
||||||
y = 64 / (NUMBER_OF_ROWS - 1 ) * COL_POSITION
|
|
||||||
|
|
||||||
Where all variables are decimels/floats.
|
|
||||||
|
|
||||||
`modifier` is a boolean, whether or not a certain key is considered a modifier (used in some effects).
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
All RGB keycodes are currently shared with the RGBLIGHT system:
|
|
||||||
|
|
||||||
* `RGB_TOG` - toggle
|
|
||||||
* `RGB_MOD` - cycle through modes
|
|
||||||
* `RGB_HUI` - increase hue
|
|
||||||
* `RGB_HUD` - decrease hue
|
|
||||||
* `RGB_SAI` - increase saturation
|
|
||||||
* `RGB_SAD` - decrease saturation
|
|
||||||
* `RGB_VAI` - increase value
|
|
||||||
* `RGB_VAD` - decrease value
|
|
||||||
* `RGB_SPI` - increase speed effect (no EEPROM support)
|
|
||||||
* `RGB_SPD` - decrease speed effect (no EEPROM support)
|
|
||||||
|
|
||||||
|
|
||||||
* `RGB_MODE_*` keycodes will generally work, but are not currently mapped to the correct effects for the RGB Matrix system
|
|
||||||
|
|
||||||
## RGB Matrix Effects
|
|
||||||
|
|
||||||
These are the effects that are currently available:
|
|
||||||
|
|
||||||
enum rgb_matrix_effects {
|
|
||||||
RGB_MATRIX_SOLID_COLOR = 1,
|
|
||||||
RGB_MATRIX_ALPHAS_MODS,
|
|
||||||
RGB_MATRIX_DUAL_BEACON,
|
|
||||||
RGB_MATRIX_GRADIENT_UP_DOWN,
|
|
||||||
RGB_MATRIX_RAINDROPS,
|
|
||||||
RGB_MATRIX_CYCLE_ALL,
|
|
||||||
RGB_MATRIX_CYCLE_LEFT_RIGHT,
|
|
||||||
RGB_MATRIX_CYCLE_UP_DOWN,
|
|
||||||
RGB_MATRIX_RAINBOW_BEACON,
|
|
||||||
RGB_MATRIX_RAINBOW_PINWHEELS,
|
|
||||||
RGB_MATRIX_RAINBOW_MOVING_CHEVRON,
|
|
||||||
RGB_MATRIX_JELLYBEAN_RAINDROPS,
|
|
||||||
RGB_MATRIX_DIGITAL_RAIN,
|
|
||||||
#ifdef RGB_MATRIX_KEYPRESSES
|
|
||||||
RGB_MATRIX_SOLID_REACTIVE,
|
|
||||||
RGB_MATRIX_REACTIVE_SIMPLE,
|
|
||||||
RGB_MATRIX_SPLASH,
|
|
||||||
RGB_MATRIX_MULTISPLASH,
|
|
||||||
RGB_MATRIX_SOLID_SPLASH,
|
|
||||||
RGB_MATRIX_SOLID_MULTISPLASH,
|
|
||||||
#endif
|
|
||||||
RGB_MATRIX_EFFECT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
You can disable a single effect by defining `DISABLE_[EFFECT_NAME]` in your `config.h`:
|
|
||||||
|
|
||||||
|
|
||||||
|Define |Description |
|
|
||||||
|---------------------------------------------------|--------------------------------------------|
|
|
||||||
|`#define DISABLE_RGB_MATRIX_ALPHAS_MODS` |Disables `RGB_MATRIX_ALPHAS_MODS` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_DUAL_BEACON` |Disables `RGB_MATRIX_DUAL_BEACON` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN` |Disables `RGB_MATRIX_GRADIENT_UP_DOWN` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_RAINDROPS` |Disables `RGB_MATRIX_RAINDROPS` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_CYCLE_ALL` |Disables `RGB_MATRIX_CYCLE_ALL` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT` |Disables `RGB_MATRIX_CYCLE_LEFT_RIGHT` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_CYCLE_UP_DOWN` |Disables `RGB_MATRIX_CYCLE_UP_DOWN` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_RAINBOW_BEACON` |Disables `RGB_MATRIX_RAINBOW_BEACON` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS` |Disables `RGB_MATRIX_RAINBOW_PINWHEELS` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON`|Disables `RGB_MATRIX_RAINBOW_MOVING_CHEVRON`|
|
|
||||||
|`#define DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS` |Disables `RGB_MATRIX_JELLYBEAN_RAINDROPS` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_DIGITAL_RAIN` |Disables `RGB_MATRIX_DIGITAL_RAIN` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_SOLID_REACTIVE` |Disables `RGB_MATRIX_SOLID_REACTIVE` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_REACTIVE_SIMPLE` |Disables `RGB_MATRIX_REACTIVE_SIMPLE` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_SPLASH` |Disables `RGB_MATRIX_SPLASH` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_MULTISPLASH` |Disables `RGB_MATRIX_MULTISPLASH` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_SOLID_SPLASH` |Disables `RGB_MATRIX_SOLID_SPLASH` |
|
|
||||||
|`#define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Disables `RGB_MATRIX_SOLID_MULTISPLASH` |
|
|
||||||
|
|
||||||
|
|
||||||
## Custom layer effects
|
|
||||||
|
|
||||||
Custom layer effects can be done by defining this in your `<keyboard>.c`:
|
|
||||||
|
|
||||||
void rgb_matrix_indicators_kb(void) {
|
|
||||||
rgb_matrix_set_color(index, red, green, blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
A similar function works in the keymap as `rgb_matrix_indicators_user`.
|
|
||||||
|
|
||||||
## Additional `config.h` Options
|
|
||||||
|
|
||||||
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses (will slow down matrix scan by a lot)
|
|
||||||
#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened)
|
|
||||||
#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
|
|
||||||
#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended
|
|
||||||
#define RGB_MATRIX_SKIP_FRAMES 1 // number of frames to skip when displaying animations (0 is full effect) if not defined defaults to 1
|
|
||||||
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
|
|
||||||
|
|
||||||
## 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:
|
|
||||||
|
|
||||||
#define EECONFIG_RGB_MATRIX (uint32_t *)16
|
|
||||||
|
|
||||||
Where `16` is an unused index from `eeconfig.h`.
|
|
||||||
|
|
||||||
## Suspended state
|
|
||||||
|
|
||||||
To use the suspend feature, add this to your `<keyboard>.c`:
|
|
||||||
|
|
||||||
void suspend_power_down_kb(void)
|
|
||||||
{
|
|
||||||
rgb_matrix_set_suspend_state(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void suspend_wakeup_init_kb(void)
|
|
||||||
{
|
|
||||||
rgb_matrix_set_suspend_state(false);
|
|
||||||
}
|
|
@ -1,243 +0,0 @@
|
|||||||
# RGB Lighting
|
|
||||||
|
|
||||||
QMK has the ability to control RGB LEDs attached to your keyboard. This is commonly called *underglow*, due to the LEDs often being mounted on the bottom of the keyboard, producing a nice diffused effect when combined with a translucent case.
|
|
||||||
|
|
||||||
![Planck with RGB Underglow](https://raw.githubusercontent.com/qmk/qmk_firmware/3774a7fcdab5544fc787f4c200be05fcd417e31f/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg)
|
|
||||||
|
|
||||||
Some keyboards come with RGB LEDs preinstalled. Others must have them installed after the fact. See the [Hardware Modification](#hardware-modification) section for information on adding RGB lighting to your keyboard.
|
|
||||||
|
|
||||||
Currently QMK supports the following addressable LEDs on AVR microcontrollers (however, the white LED in RGBW variants is not supported):
|
|
||||||
|
|
||||||
* WS2811, WS2812, WS2812B, WS2812C, etc.
|
|
||||||
* SK6812, SK6812MINI, SK6805
|
|
||||||
|
|
||||||
These LEDs are called "addressable" because instead of using a wire per color, each LED contains a small microchip that understands a special protocol sent over a single wire. The chip passes on the remaining data to the next LED, allowing them to be chained together. In this way, you can easily control the color of the individual LEDs.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
On keyboards with onboard RGB LEDs, it is usually enabled by default. If it is not working for you, check that your `rules.mk` includes the following:
|
|
||||||
|
|
||||||
```make
|
|
||||||
RGBLIGHT_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these.
|
|
||||||
|
|
||||||
|Define |Description |
|
|
||||||
|---------------|---------------------------------------------------------------------------------------------------------|
|
|
||||||
|`RGB_DI_PIN` |The pin connected to the data pin of the LEDs |
|
|
||||||
|`RGBLED_NUM` |The number of LEDs connected |
|
|
||||||
|`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half directly wired to `RGB_DI_PIN` |
|
|
||||||
|
|
||||||
Then you should be able to use the keycodes below to change the RGB lighting to your liking.
|
|
||||||
|
|
||||||
### Color Selection
|
|
||||||
|
|
||||||
QMK uses [Hue, Saturation, and Value](https://en.wikipedia.org/wiki/HSL_and_HSV) to select colors rather than RGB. The color wheel below demonstrates how this works.
|
|
||||||
|
|
||||||
<img src="gitbook/images/color-wheel.svg" alt="HSV Color Wheel" width="250"/>
|
|
||||||
|
|
||||||
Changing the **Hue** cycles around the circle.
|
|
||||||
Changing the **Saturation** moves between the inner and outer sections of the wheel, affecting the intensity of the color.
|
|
||||||
Changing the **Value** sets the overall brightness.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-------------------|----------|--------------------------------------------------------------------|
|
|
||||||
|`RGB_TOG` | |Toggle RGB lighting on or off |
|
|
||||||
|`RGB_MODE_FORWARD` |`RGB_MOD` |Cycle through modes, reverse direction when Shift is held |
|
|
||||||
|`RGB_MODE_REVERSE` |`RGB_RMOD`|Cycle through modes in reverse, forward direction when Shift is held|
|
|
||||||
|`RGB_HUI` | |Increase hue |
|
|
||||||
|`RGB_HUD` | |Decrease hue |
|
|
||||||
|`RGB_SAI` | |Increase saturation |
|
|
||||||
|`RGB_SAD` | |Decrease saturation |
|
|
||||||
|`RGB_VAI` | |Increase value (brightness) |
|
|
||||||
|`RGB_VAD` | |Decrease value (brightness) |
|
|
||||||
|`RGB_MODE_PLAIN` |`RGB_M_P `|Static (no animation) mode |
|
|
||||||
|`RGB_MODE_BREATHE` |`RGB_M_B` |Breathing animation mode |
|
|
||||||
|`RGB_MODE_RAINBOW` |`RGB_M_R` |Rainbow animation mode |
|
|
||||||
|`RGB_MODE_SWIRL` |`RGB_M_SW`|Swirl animation mode |
|
|
||||||
|`RGB_MODE_SNAKE` |`RGB_M_SN`|Snake animation mode |
|
|
||||||
|`RGB_MODE_KNIGHT` |`RGB_M_K` |"Knight Rider" animation mode |
|
|
||||||
|`RGB_MODE_XMAS` |`RGB_M_X` |Christmas animation mode |
|
|
||||||
|`RGB_MODE_GRADIENT`|`RGB_M_G` |Static gradient animation mode |
|
|
||||||
|`RGB_MODE_RGBTEST` |`RGB_M_T` |Red, Green, Blue test animation mode |
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Your RGB lighting can be configured by placing these `#define`s in your `config.h`:
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|---------------------|-------------|-----------------------------------------------------------------------------|
|
|
||||||
|`RGBLIGHT_HUE_STEP` |`10` |The number of steps to cycle through the hue by |
|
|
||||||
|`RGBLIGHT_SAT_STEP` |`17` |The number of steps to increment the saturation by |
|
|
||||||
|`RGBLIGHT_VAL_STEP` |`17` |The number of steps to increment the brightness by |
|
|
||||||
|`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level |
|
|
||||||
|`RGBLIGHT_SLEEP` |*Not defined*|If defined, the RGB lighting will be switched off when the host goes to sleep|
|
|
||||||
|
|
||||||
## Animations
|
|
||||||
|
|
||||||
|
|
||||||
Not only can this lighting be whatever color you want,
|
|
||||||
if `RGBLIGHT_EFFECT_xxxx` or `RGBLIGHT_ANIMATIONS` is defined, you also have a number of animation modes at your disposal:
|
|
||||||
|
|
||||||
|Mode number symbol |Additional number |Description |
|
|
||||||
|-----------------------------|-------------------|---------------------------------------|
|
|
||||||
|`RGBLIGHT_MODE_STATIC_LIGHT` | *None* |Solid color (this mode is always enabled) |
|
|
||||||
|`RGBLIGHT_MODE_BREATHING` | 0,1,2,3 |Solid color breathing |
|
|
||||||
|`RGBLIGHT_MODE_RAINBOW_MOOD` | 0,1,2 |Cycling rainbow |
|
|
||||||
|`RGBLIGHT_MODE_RAINBOW_SWIRL`| 0,1,2,3,4,5 |Swirling rainbow |
|
|
||||||
|`RGBLIGHT_MODE_SNAKE` | 0,1,2,3,4,5 |Snake |
|
|
||||||
|`RGBLIGHT_MODE_KNIGHT` | 0,1,2 |Knight |
|
|
||||||
|`RGBLIGHT_MODE_CHRISTMAS` | *None* |Christmas |
|
|
||||||
|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient |
|
|
||||||
|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test |
|
|
||||||
|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating |
|
|
||||||
|
|
||||||
Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
|
|
||||||
|
|
||||||
Note: For versions older than 0.6.117, The mode numbers were written directly. In `quantum/rgblight.h` there is a contrast table between the old mode number and the current symbol.
|
|
||||||
|
|
||||||
The following options can be used to tweak the various animations:
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|------------------------------------|-------------|-------------------------------------------------------------------------------------|
|
|
||||||
|`RGBLIGHT_EFFECT_BREATHING` |*Not defined*|If defined, enable breathing animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_RAINBOW_MOOD` |*Not defined*|If defined, enable rainbow mood animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_RAINBOW_SWIRL` |*Not defined*|If defined, enable rainbow swirl animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|If defined, enable snake animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_KNIGHT` |*Not defined*|If defined, enable knight animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_CHRISTMAS` |*Not defined*|If defined, enable christmas animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|If defined, enable static gradient mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|If defined, enable RGB test animation mode. |
|
|
||||||
|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|If defined, enable alternating animation mode. |
|
|
||||||
|`RGBLIGHT_ANIMATIONS` |*Not defined*|If defined, enables all additional animation modes |
|
|
||||||
|`RGBLIGHT_EFFECT_BREATHE_CENTER` |`1.85` |Used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 |
|
|
||||||
|`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 |
|
|
||||||
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
|
||||||
|`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation |
|
|
||||||
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
|
||||||
|`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLED_NUM` |The number of LEDs to have the "Knight" animation travel |
|
|
||||||
|`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`1000` |How long to wait between light changes for the "Christmas" animation, in milliseconds|
|
|
||||||
|`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation |
|
|
||||||
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`360` |Range adjustment for the rainbow swirl effect to get different swirls |
|
|
||||||
|
|
||||||
You can also modify the speeds that the different modes animate at:
|
|
||||||
|
|
||||||
Here is a quick demo on Youtube (with NPKC KC60) (https://www.youtube.com/watch?v=VKrpPAHlisY).
|
|
||||||
|
|
||||||
```c
|
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Solid color breathing" animations
|
|
||||||
const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
|
|
||||||
|
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Cycling rainbow" animations
|
|
||||||
const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
|
|
||||||
|
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Swirling rainbow" animations
|
|
||||||
const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
|
|
||||||
|
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Snake" animations
|
|
||||||
const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
|
|
||||||
|
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations
|
|
||||||
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
|
|
||||||
|
|
||||||
// These control which hues are selected for each of the "Static gradient" modes
|
|
||||||
const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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:
|
|
||||||
|
|
||||||
|Function |Description |
|
|
||||||
|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
|`rgblight_enable()` |Turn LEDs on, based on their previous state |
|
|
||||||
|`rgblight_enable_noeeprom()` |Turn LEDs on, based on their previous state (not written to EEPROM) |
|
|
||||||
|`rgblight_disable()` |Turn LEDs off |
|
|
||||||
|`rgblight_disable_noeeprom()` |Turn LEDs off (not written to EEPROM) |
|
|
||||||
|`rgblight_mode(x)` |Set the mode, if RGB animations are enabled |
|
|
||||||
|`rgblight_mode_noeeprom(x)` |Set the mode, if RGB animations are enabled (not written to EEPROM) |
|
|
||||||
|`rgblight_setrgb(r, g, b)` |Set all LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_setrgb_at(r, g, b, led)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `led` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
|
|
||||||
|`rgblight_setrgb_range(r, g, b, start, end)`|Set a continuous range of LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
|
|
||||||
|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_sethsv(h, s, v)` |Set all LEDs to the given HSV value where `h` is between 0 and 360 and `s`/`v` are between 0 and 255 |
|
|
||||||
|`rgblight_sethsv_noeeprom(h, s, v)` |Set all LEDs to the given HSV value where `h` is between 0 and 360 and `s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_sethsv_at(h, s, v, led)` |Set a single LED to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255, and `led` is between 0 and `RGBLED_NUM` (not written to EEPROM)|
|
|
||||||
|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
|
|
||||||
|`rgblight_sethsv_master(h, s, v)` |Set the LEDs on the master side to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_sethsv_slave(h, s, v)` |Set the LEDs on the slave side to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
||||||
|`rgblight_toggle()` |Toggle all LEDs between on and off |
|
|
||||||
|`rgblight_toggle_noeeprom()` |Toggle all LEDs between on and off (not written to EEPROM) |
|
|
||||||
|`rgblight_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations |
|
|
||||||
|`rgblight_step_noeeprom()` |Change the mode to the next RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
|
||||||
|`rgblight_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations |
|
|
||||||
|`rgblight_step_reverse_noeeprom()` |Change the mode to the previous RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
|
||||||
|`rgblight_increase_hue()` |Increase the hue for all LEDs. This wraps around at maximum hue |
|
|
||||||
|`rgblight_increase_hue_noeeprom()` |Increase the hue for all LEDs. This wraps around at maximum hue (not written to EEPROM) |
|
|
||||||
|`rgblight_decrease_hue()` |Decrease the hue for all LEDs. This wraps around at minimum hue |
|
|
||||||
|`rgblight_decrease_hue_noeeprom()` |Decrease the hue for all LEDs. This wraps around at minimum hue (not written to EEPROM) |
|
|
||||||
|`rgblight_increase_sat()` |Increase the saturation for all LEDs. This wraps around at maximum saturation |
|
|
||||||
|`rgblight_increase_sat_noeeprom()` |Increase the saturation for all LEDs. This wraps around at maximum saturation (not written to EEPROM) |
|
|
||||||
|`rgblight_decrease_sat()` |Decrease the saturation for all LEDs. This wraps around at minimum saturation |
|
|
||||||
|`rgblight_decrease_sat_noeeprom()` |Decrease the saturation for all LEDs. This wraps around at minimum saturation (not written to EEPROM) |
|
|
||||||
|`rgblight_increase_val()` |Increase the value for all LEDs. This wraps around at maximum value |
|
|
||||||
|`rgblight_increase_val_noeeprom()` |Increase the value for all LEDs. This wraps around at maximum value (not written to EEPROM) |
|
|
||||||
|`rgblight_decrease_val()` |Decrease the value for all LEDs. This wraps around at minimum value |
|
|
||||||
|`rgblight_decrease_val_noeeprom()` |Decrease the value for all LEDs. This wraps around at minimum value (not written to EEPROM) |
|
|
||||||
|
|
||||||
Additionally, [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h) defines several predefined shortcuts for various colors. Feel free to add to this list!
|
|
||||||
|
|
||||||
## Changing the order of the LEDs
|
|
||||||
|
|
||||||
If you want to make the logical order of LEDs different from the electrical connection order, you can do this by defining the `RGBLIGHT_LED_MAP` macro in your `config.h`.
|
|
||||||
|
|
||||||
By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED with addressing in reverse order of the electrical connection order.
|
|
||||||
|
|
||||||
```c
|
|
||||||
// config.h
|
|
||||||
|
|
||||||
#define RGBLED_NUM 10
|
|
||||||
#define RGBLIGHT_LED_MAP { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
For keyboards that use the RGB LEDs as a backlight for each key, you can also define it as in the example below.
|
|
||||||
|
|
||||||
```c
|
|
||||||
// config.h
|
|
||||||
|
|
||||||
#define RGBLED_NUM 30
|
|
||||||
|
|
||||||
/* RGB LED Conversion macro from physical array to electric array */
|
|
||||||
#define LED_LAYOUT( \
|
|
||||||
L00, L01, L02, L03, L04, L05, \
|
|
||||||
L10, L11, L12, L13, L14, L15, \
|
|
||||||
L20, L21, L22, L23, L24, L25, \
|
|
||||||
L30, L31, L32, L33, L34, L35, \
|
|
||||||
L40, L41, L42, L43, L44, L45 ) \
|
|
||||||
{ \
|
|
||||||
L05, L04, L03, L02, L01, L00, \
|
|
||||||
L10, L11, L12, L13, L14, L15, \
|
|
||||||
L25, L24, L23, L22, L21, L20, \
|
|
||||||
L30, L31, L32, L33, L34, L35, \
|
|
||||||
L46, L45, L44, L43, L42, L41 \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RGB LED logical order map */
|
|
||||||
/* Top->Bottom, Right->Left */
|
|
||||||
#define RGBLIGHT_LED_MAP LED_LAYOUT( \
|
|
||||||
25, 20, 15, 10, 5, 0, \
|
|
||||||
26, 21, 16, 11, 6, 1, \
|
|
||||||
27, 22, 17, 12, 7, 2, \
|
|
||||||
28, 23, 18, 13, 8, 3, \
|
|
||||||
29, 24, 19, 14, 9, 4 )
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Hardware Modification
|
|
||||||
|
|
||||||
If your keyboard lacks onboard underglow LEDs, you may often be able to solder on an RGB LED strip yourself. You will need to find an unused pin to wire to the data pin of your LED strip. Some keyboards may break out unused pins from the MCU to make soldering easier. The other two pins, VCC and GND, must also be connected to the appropriate power pins.
|
|
@ -1,37 +0,0 @@
|
|||||||
# Space Cadet Shift: The Future, Built In
|
|
||||||
|
|
||||||
Steve Losh described the [Space Cadet Shift](http://stevelosh.com/blog/2012/10/a-modern-space-cadet/) quite well. Essentially, when you tap Left Shift on its own, you get an opening parenthesis; tap Right Shift on its own and you get the closing one. When held, the Shift keys function as normal. Yes, it's as cool as it sounds.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Replace the Left Shift key in your keymap with `KC_LSPO` (Left Shift, Parenthesis Open), and Right Shift with `KC_RSPC` (Right Shift, Parenthesis Close).
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Keycode |Description |
|
|
||||||
|---------|--------------------------------------|
|
|
||||||
|`KC_LSPO`|Left Shift when held, `(` when tapped |
|
|
||||||
|`KC_RSPC`|Right Shift when held, `)` when tapped|
|
|
||||||
|
|
||||||
## Caveats
|
|
||||||
|
|
||||||
Space Cadet's functionality can conflict with the default Command functionality when both Shift keys are held at the same time. Make sure that Command is disabled in your `rules.mk` with:
|
|
||||||
|
|
||||||
```make
|
|
||||||
COMMAND_ENABLE = no
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
By default Space Cadet assumes a US ANSI layout, but if your layout uses different keys for parentheses, you can redefine them in your `config.h`.
|
|
||||||
You can also disable the rollover, allowing you to use the opposite Shift key to cancel the Space Cadet state in the event of an erroneous press, instead of emitting a pair of parentheses when the keys are released.
|
|
||||||
Also, by default, the Space Cadet applies modifiers LSPO_MOD and RSPC_MOD to keys defined by LSPO_KEY and RSPC_KEY. You can override this behavior by redefining those variables in your `config.h`. You can also prevent the Space Cadet to apply a modifier by defining DISABLE_SPACE_CADET_MODIFIER in your `config.h`.
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|------------------------------|-------------|--------------------------------------------------------------------------------|
|
|
||||||
|`LSPO_KEY` |`KC_9` |The keycode to send when Left Shift is tapped |
|
|
||||||
|`RSPC_KEY` |`KC_0` |The keycode to send when Right Shift is tapped |
|
|
||||||
|`LSPO_MOD` |`KC_LSFT` |The keycode to send when Left Shift is tapped |
|
|
||||||
|`RSPC_MOD` |`KC_RSFT` |The keycode to send when Right Shift is tapped |
|
|
||||||
|`DISABLE_SPACE_CADET_ROLLOVER`|*Not defined*|If defined, use the opposite Shift key to cancel Space Cadet |
|
|
||||||
|`DISABLE_SPACE_CADET_MODIFIER`|*Not defined*|If defined, prevent the Space Cadet to apply a modifier to LSPO_KEY and RSPC_KEY|
|
|
@ -1,31 +0,0 @@
|
|||||||
# Space Cadet Shift Enter
|
|
||||||
|
|
||||||
Based on the [Space Cadet Shift](feature_space_cadet_shift.md) feature. Tap the Shift key on its own, and it behaves like Enter. When held, the Shift functions as normal.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Replace any Shift key in your keymap with `KC_SFTENT` (Shift, Enter), and you're done.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Keycode |Description |
|
|
||||||
|-----------|----------------------------------------|
|
|
||||||
|`KC_SFTENT`|Right Shift when held, Enter when tapped|
|
|
||||||
|
|
||||||
## Caveats
|
|
||||||
|
|
||||||
As with Space Cadet Shift, this feature may conflict with Command, so it should be disabled in your `rules.mk` with:
|
|
||||||
|
|
||||||
```make
|
|
||||||
COMMAND_ENABLE = no
|
|
||||||
```
|
|
||||||
|
|
||||||
This feature also uses the same timers as Space Cadet Shift, so using them in tandem may produce strange results.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
By default Space Cadet assumes a US ANSI layout, but if you'd like to use a different key for Enter, you can redefine it in your `config.h`:
|
|
||||||
|
|
||||||
|Define |Default |Description |
|
|
||||||
|------------|--------|------------------------------------------------|
|
|
||||||
|`SFTENT_KEY`|`KC_ENT`|The keycode to send when the Shift key is tapped|
|
|
@ -1,132 +0,0 @@
|
|||||||
# 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 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 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`.
|
|
||||||
|
|
||||||
When QMK speaks to Plover over a steno protocol Plover will not use the keyboard as input. This means that you can switch back and forth between a standard keyboard and your steno keyboard, or even switch layers from Plover to standard and back without needing to activate/deactivate Plover.
|
|
||||||
|
|
||||||
In this mode Plover expects to speak with a steno machine over a serial port so QMK will present itself to the operating system as a virtual serial port in addition to a keyboard. By default QMK will speak the TX Bolt protocol but can be switched to GeminiPR; the last protocol used is stored in non-volatile memory so QMK will use the same protocol on restart.
|
|
||||||
|
|
||||||
> 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 communicates the status of 24 keys over a very simple protocol in variable-sized (1-5 byte) packets.
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
void matrix_init_user() {
|
|
||||||
steno_set_mode(STENO_MODE_GEMINI); // or STENO_MODE_BOLT
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you have your keyboard flashed launch Plover. Click the 'Configure...' button. In the 'Machine' tab select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control).
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
* [Learn Plover!](https://sites.google.com/site/ploverdoc/)
|
|
||||||
* [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
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
|
||||||
As defined in `keymap_steno.h`.
|
|
||||||
|
|
||||||
> Note: TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
|
|
||||||
|
|
||||||
|GeminiPR|TX Bolt|Steno Key|
|
|
||||||
|--------|-------|-----------|
|
|
||||||
|`STN_N1`|`STN_NUM`|Number bar #1|
|
|
||||||
|`STN_N2`|`STN_NUM`|Number bar #2|
|
|
||||||
|`STN_N3`|`STN_NUM`|Number bar #3|
|
|
||||||
|`STN_N4`|`STN_NUM`|Number bar #4|
|
|
||||||
|`STN_N5`|`STN_NUM`|Number bar #5|
|
|
||||||
|`STN_N6`|`STN_NUM`|Number bar #6|
|
|
||||||
|`STN_N7`|`STN_NUM`|Number bar #7|
|
|
||||||
|`STN_N8`|`STN_NUM`|Number bar #8|
|
|
||||||
|`STN_N9`|`STN_NUM`|Number bar #9|
|
|
||||||
|`STN_NA`|`STN_NUM`|Number bar #A|
|
|
||||||
|`STN_NB`|`STN_NUM`|Number bar #B|
|
|
||||||
|`STN_NC`|`STN_NUM`|Number bar #C|
|
|
||||||
|`STN_S1`|`STN_SL`| `S-` upper|
|
|
||||||
|`STN_S2`|`STN_SL`| `S-` lower|
|
|
||||||
|`STN_TL`|`STN_TL`| `T-`|
|
|
||||||
|`STN_KL`|`STN_KL`| `K-`|
|
|
||||||
|`STN_PL`|`STN_PL`| `P-`|
|
|
||||||
|`STN_WL`|`STN_WL`| `W-`|
|
|
||||||
|`STN_HL`|`STN_HL`| `H-`|
|
|
||||||
|`STN_RL`|`STN_RL`| `R-`|
|
|
||||||
|`STN_A`|`STN_A`| `A` vowel|
|
|
||||||
|`STN_O`|`STN_O`| `O` vowel|
|
|
||||||
|`STN_ST1`|`STN_STR`| `*` upper-left |
|
|
||||||
|`STN_ST2`|`STN_STR`| `*` lower-left|
|
|
||||||
|`STN_ST3`|`STN_STR`| `*` upper-right|
|
|
||||||
|`STN_ST4`|`STN_STR`| `*` lower-right|
|
|
||||||
|`STN_E`|`STN_E`| `E` vowel|
|
|
||||||
|`STN_U`|`STN_U`| `U` vowel|
|
|
||||||
|`STN_FR`|`STN_FR`| `-F`|
|
|
||||||
|`STN_PR`|`STN_PR`| `-P`|
|
|
||||||
|`STN_RR`|`STN_RR`| `-R`|
|
|
||||||
|`STN_BR`|`STN_BR`| `-B`|
|
|
||||||
|`STN_LR`|`STN_LR`| `-L`|
|
|
||||||
|`STN_GR`|`STN_GR`| `-G`|
|
|
||||||
|`STN_TR`|`STN_TR`| `-T`|
|
|
||||||
|`STN_SR`|`STN_SR`| `-S`|
|
|
||||||
|`STN_DR`|`STN_DR`| `-D`|
|
|
||||||
|`STN_ZR`|`STN_ZR`| `-Z`|
|
|
||||||
|`STN_FN`|| (GeminiPR only)|
|
|
||||||
|`STN_RES1`||(GeminiPR only)|
|
|
||||||
|`STN_RES2`||(GeminiPR only)|
|
|
||||||
|`STN_PWR`||(GeminiPR only)|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
# Swap-Hands Action
|
|
||||||
|
|
||||||
The swap-hands action allows support for one-handed typing without requiring a separate layer. Set `SWAP_HANDS_ENABLE` in the Makefile and define a `hand_swap_config` entry in your keymap. Now whenever the `ACTION_SWAP_HANDS` command key is pressed the keyboard is mirrored. For instance, to type "Hello, World" on QWERTY you would type `^Ge^s^s^w^c W^wr^sd`
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
The configuration table is a simple 2-dimensional array to map from column/row to new column/row. Example `hand_swap_config` for Planck:
|
|
||||||
|
|
||||||
```C
|
|
||||||
const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
{{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
|
|
||||||
{{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
|
|
||||||
{{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
|
|
||||||
{{11, 3}, {10, 3}, {9, 3}, {8, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the array indices are reversed same as the matrix and the values are of type `keypos_t` which is `{col, row}` and all values are zero-based. In the example above, `hand_swap_config[2][4]` (third row, fifth column) would return `{7, 2}` (third row, eighth column). Yes, this is confusing.
|
|
||||||
|
|
||||||
## Swap Keycodes
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|-----------|-------------------------------------------------------------------------|
|
|
||||||
|`SH_T(key)`|Sends `key` with a tap; momentary swap when held. |
|
|
||||||
|`SH_ON` |Turns on swapping and leaves it on. |
|
|
||||||
|`SH_OFF` |Turn off swapping and leaves it off. Good for returning to a known state.|
|
|
||||||
|`SH_MON` |Swaps hands when pressed, returns to normal when released (momentary). |
|
|
||||||
|`SH_MOFF` |Momentarily turns off swap. |
|
|
||||||
|`SH_TG` |Toggles swap on and off with every key press. |
|
|
||||||
|`SH_TT` |Toggles with a tap; momentary when held. |
|
|
@ -1,399 +0,0 @@
|
|||||||
# Tap Dance: A Single Key Can Do 3, 5, or 100 Different Things
|
|
||||||
|
|
||||||
<!-- FIXME: Break this up into multiple sections -->
|
|
||||||
|
|
||||||
Hit the semicolon key once, send a semicolon. Hit it twice, rapidly -- send a colon. Hit it three times, and your keyboard's LEDs do a wild dance. That's just one example of what Tap Dance can do. It's one of the nicest community-contributed features in the firmware, conceived and created by [algernon](https://github.com/algernon) in [#451](https://github.com/qmk/qmk_firmware/pull/451). Here's how algernon describes the feature:
|
|
||||||
|
|
||||||
With this feature one can specify keys that behave differently, based on the amount of times they have been tapped, and when interrupted, they get handled before the interrupter.
|
|
||||||
|
|
||||||
To make it clear how this is different from `ACTION_FUNCTION_TAP`, let's explore a certain setup! We want one key to send `Space` on single tap, but `Enter` on double-tap.
|
|
||||||
|
|
||||||
With `ACTION_FUNCTION_TAP`, it is quite a rain-dance to set this up, and has the problem that when the sequence is interrupted, the interrupting key will be sent first. Thus, `SPC a` will result in `a SPC` being sent, if they are typed within `TAPPING_TERM`. With the tap dance feature, that'll come out as `SPC a`, correctly.
|
|
||||||
|
|
||||||
The implementation hooks into two parts of the system, to achieve this: into `process_record_quantum()`, and the matrix scan. We need the latter to be able to time out a tap sequence even when a key is not being pressed, so `SPC` alone will time out and register after `TAPPING_TERM` time.
|
|
||||||
|
|
||||||
But lets start with how to use it, first!
|
|
||||||
|
|
||||||
First, you will need `TAP_DANCE_ENABLE=yes` in your `rules.mk`, because the feature is disabled by default. This adds a little less than 1k to the firmware size. Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that - similar to `F()`, takes a number, which will later be used as an index into the `tap_dance_actions` array.
|
|
||||||
|
|
||||||
This array specifies what actions shall be taken when a tap-dance key is in action. Currently, there are five possible options:
|
|
||||||
|
|
||||||
* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: Sends the `kc1` keycode when tapped once, `kc2` otherwise. When the key is held, the appropriate keycode is registered: `kc1` when pressed and held, `kc2` when tapped once, then pressed and held.
|
|
||||||
* `ACTION_TAP_DANCE_DUAL_ROLE(kc, layer)`: Sends the `kc` keycode when tapped once, or moves to `layer`. (this functions like the `TO` layer keycode).
|
|
||||||
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
|
|
||||||
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
|
|
||||||
* `ACTION_TAP_DANCE_FN_ADVANCED_TIME(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn, tap_specific_tapping_term)`: This functions identically to the `ACTION_TAP_DANCE_FN_ADVANCED` function, but uses a custom tapping term for it, instead of the predefined `TAPPING_TERM`.
|
|
||||||
|
|
||||||
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
|
|
||||||
|
|
||||||
!> Keep in mind that only [basic keycodes](keycodes_basic.md) are supported here. Custom keycodes are not supported.
|
|
||||||
|
|
||||||
And that's the bulk of it!
|
|
||||||
|
|
||||||
And now, on to the explanation of how it works!
|
|
||||||
|
|
||||||
The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and the timer.
|
|
||||||
|
|
||||||
This means that you have `TAPPING_TERM` time to tap the key again, you do not have to input all the taps within that timeframe. This allows for longer tap counts, with minimal impact on responsiveness.
|
|
||||||
|
|
||||||
Our next stop is `matrix_scan_tap_dance()`. This handles the timeout of tap-dance keys.
|
|
||||||
|
|
||||||
For the sake of flexibility, tap-dance actions can be either a pair of keycodes, or a user function. The latter allows one to handle higher tap counts, or do extra things, like blink the LEDs, fiddle with the backlighting, and so on. This is accomplished by using an union, and some clever macros.
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
|
|
||||||
## Simple Example
|
|
||||||
|
|
||||||
Here's a simple example for a single definition:
|
|
||||||
|
|
||||||
1. In your `rules.mk`, add `TAP_DANCE_ENABLE = yes`
|
|
||||||
2. In your `config.h` (which you can copy from `qmk_firmware/keyboards/planck/config.h` to your keymap directory), add `#define TAPPING_TERM 200`
|
|
||||||
3. In your `keymap.c` file, define the variables and definitions, then add to your keymap:
|
|
||||||
|
|
||||||
```c
|
|
||||||
//Tap Dance Declarations
|
|
||||||
enum {
|
|
||||||
TD_ESC_CAPS = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
//Tap Dance Definitions
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
//Tap once for Esc, twice for Caps Lock
|
|
||||||
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS)
|
|
||||||
// Other declarations would go here, separated by commas, if you have them
|
|
||||||
};
|
|
||||||
|
|
||||||
//In Layer declaration, add tap dance item in place of a key code
|
|
||||||
TD(TD_ESC_CAPS)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Complex Examples
|
|
||||||
|
|
||||||
This section details several complex tap dance examples.
|
|
||||||
All the enums used in the examples are declared like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// Enums defined for all examples:
|
|
||||||
enum {
|
|
||||||
CT_SE = 0,
|
|
||||||
CT_CLN,
|
|
||||||
CT_EGG,
|
|
||||||
CT_FLSH,
|
|
||||||
X_TAP_DANCE
|
|
||||||
};
|
|
||||||
```
|
|
||||||
### Example 1: Send `:` on Single Tap, `;` on Double Tap
|
|
||||||
```c
|
|
||||||
void dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
if (state->count == 1) {
|
|
||||||
register_code (KC_RSFT);
|
|
||||||
register_code (KC_SCLN);
|
|
||||||
} else {
|
|
||||||
register_code (KC_SCLN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
if (state->count == 1) {
|
|
||||||
unregister_code (KC_RSFT);
|
|
||||||
unregister_code (KC_SCLN);
|
|
||||||
} else {
|
|
||||||
unregister_code (KC_SCLN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//All tap dance functions would go here. Only showing this one.
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
### Example 2: Send "Safety Dance!" After 100 Taps
|
|
||||||
```c
|
|
||||||
void dance_egg (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
if (state->count >= 100) {
|
|
||||||
SEND_STRING ("Safety dance!");
|
|
||||||
reset_tap_dance (state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 3: Turn LED Lights On Then Off, One at a Time
|
|
||||||
|
|
||||||
```c
|
|
||||||
// on each tap, light up one led, from right to left
|
|
||||||
// on the forth tap, turn them off from right to left
|
|
||||||
void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
switch (state->count) {
|
|
||||||
case 1:
|
|
||||||
ergodox_right_led_3_on();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ergodox_right_led_2_on();
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ergodox_right_led_1_on();
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
ergodox_right_led_3_off();
|
|
||||||
_delay_ms(50);
|
|
||||||
ergodox_right_led_2_off();
|
|
||||||
_delay_ms(50);
|
|
||||||
ergodox_right_led_1_off();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// on the fourth tap, set the keyboard on flash state
|
|
||||||
void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
if (state->count >= 4) {
|
|
||||||
reset_keyboard();
|
|
||||||
reset_tap_dance(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the flash state didn't happen, then turn off LEDs, left to right
|
|
||||||
void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
ergodox_right_led_1_off();
|
|
||||||
_delay_ms(50);
|
|
||||||
ergodox_right_led_2_off();
|
|
||||||
_delay_ms(50);
|
|
||||||
ergodox_right_led_3_off();
|
|
||||||
}
|
|
||||||
|
|
||||||
//All tap dances now put together. Example 3 is "CT_FLASH"
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
[CT_SE] = ACTION_TAP_DANCE_DOUBLE (KC_SPC, KC_ENT)
|
|
||||||
,[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
|
|
||||||
,[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
|
|
||||||
,[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED (dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 4: 'Quad Function Tap-Dance'
|
|
||||||
|
|
||||||
By [DanielGGordon](https://github.com/danielggordon)
|
|
||||||
|
|
||||||
Allow one key to have 4 (or more) functions, depending on number of presses, and if the key is held or tapped.
|
|
||||||
Below is a specific example:
|
|
||||||
* Tap = Send `x`
|
|
||||||
* Hold = Send `Control`
|
|
||||||
* Double Tap = Send `Escape`
|
|
||||||
* Double Tap and Hold = Send `Alt`
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
You will need a few things that can be used for 'Quad Function Tap-Dance'.
|
|
||||||
|
|
||||||
You'll need to add these to the top of your `keymap.c` file, before your keymap.
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct {
|
|
||||||
bool is_press_action;
|
|
||||||
int state;
|
|
||||||
} tap;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SINGLE_TAP = 1,
|
|
||||||
SINGLE_HOLD = 2,
|
|
||||||
DOUBLE_TAP = 3,
|
|
||||||
DOUBLE_HOLD = 4,
|
|
||||||
DOUBLE_SINGLE_TAP = 5, //send two single taps
|
|
||||||
TRIPLE_TAP = 6,
|
|
||||||
TRIPLE_HOLD = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
//Tap dance enums
|
|
||||||
enum {
|
|
||||||
X_CTL = 0,
|
|
||||||
SOME_OTHER_DANCE
|
|
||||||
};
|
|
||||||
|
|
||||||
int cur_dance (qk_tap_dance_state_t *state);
|
|
||||||
|
|
||||||
//for the x tap dance. Put it here so it can be used in any keymap
|
|
||||||
void x_finished (qk_tap_dance_state_t *state, void *user_data);
|
|
||||||
void x_reset (qk_tap_dance_state_t *state, void *user_data);
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, at the bottom of your `keymap.c` file, you'll need to add the following:
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Return an integer that corresponds to what kind of tap dance should be executed.
|
|
||||||
*
|
|
||||||
* How to figure out tap dance state: interrupted and pressed.
|
|
||||||
*
|
|
||||||
* Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit
|
|
||||||
* under the tapping term. This is typically indicitive that you are trying to "tap" the key.
|
|
||||||
*
|
|
||||||
* Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
|
|
||||||
* has ended, but the key is still being pressed down. This generally means the key is being "held".
|
|
||||||
*
|
|
||||||
* One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
|
|
||||||
* feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
|
|
||||||
* For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
|
|
||||||
*
|
|
||||||
* Good places to put an advanced tap dance:
|
|
||||||
* z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon
|
|
||||||
*
|
|
||||||
* Criteria for "good placement" of a tap dance key:
|
|
||||||
* Not a key that is hit frequently in a sentence
|
|
||||||
* Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
|
|
||||||
* in a web form. So 'tab' would be a poor choice for a tap dance.
|
|
||||||
* Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
|
|
||||||
* letter 'p', the word 'pepper' would be quite frustating to type.
|
|
||||||
*
|
|
||||||
* For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int cur_dance (qk_tap_dance_state_t *state) {
|
|
||||||
if (state->count == 1) {
|
|
||||||
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
|
||||||
//key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
|
|
||||||
else return SINGLE_HOLD;
|
|
||||||
}
|
|
||||||
else if (state->count == 2) {
|
|
||||||
/*
|
|
||||||
* DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
|
|
||||||
* action when hitting 'pp'. Suggested use case for this return value is when you want to send two
|
|
||||||
* keystrokes of the key, and not the 'double tap' action/macro.
|
|
||||||
*/
|
|
||||||
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
|
||||||
else if (state->pressed) return DOUBLE_HOLD;
|
|
||||||
else return DOUBLE_TAP;
|
|
||||||
}
|
|
||||||
//Assumes no one is trying to type the same letter three times (at least not quickly).
|
|
||||||
//If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
|
|
||||||
//an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
|
|
||||||
if (state->count == 3) {
|
|
||||||
if (state->interrupted || !state->pressed) return TRIPLE_TAP;
|
|
||||||
else return TRIPLE_HOLD;
|
|
||||||
}
|
|
||||||
else return 8; //magic number. At some point this method will expand to work for more presses
|
|
||||||
}
|
|
||||||
|
|
||||||
//instanalize an instance of 'tap' for the 'x' tap dance.
|
|
||||||
static tap xtap_state = {
|
|
||||||
.is_press_action = true,
|
|
||||||
.state = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
void x_finished (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
xtap_state.state = cur_dance(state);
|
|
||||||
switch (xtap_state.state) {
|
|
||||||
case SINGLE_TAP: register_code(KC_X); break;
|
|
||||||
case SINGLE_HOLD: register_code(KC_LCTRL); break;
|
|
||||||
case DOUBLE_TAP: register_code(KC_ESC); break;
|
|
||||||
case DOUBLE_HOLD: register_code(KC_LALT); break;
|
|
||||||
case DOUBLE_SINGLE_TAP: register_code(KC_X); unregister_code(KC_X); register_code(KC_X);
|
|
||||||
//Last case is for fast typing. Assuming your key is `f`:
|
|
||||||
//For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`.
|
|
||||||
//In order to type `ff` when typing fast, the next character will have to be hit within the `TAPPING_TERM`, which by default is 200ms.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void x_reset (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
switch (xtap_state.state) {
|
|
||||||
case SINGLE_TAP: unregister_code(KC_X); break;
|
|
||||||
case SINGLE_HOLD: unregister_code(KC_LCTRL); break;
|
|
||||||
case DOUBLE_TAP: unregister_code(KC_ESC); break;
|
|
||||||
case DOUBLE_HOLD: unregister_code(KC_LALT);
|
|
||||||
case DOUBLE_SINGLE_TAP: unregister_code(KC_X);
|
|
||||||
}
|
|
||||||
xtap_state.state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
[X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL,x_finished, x_reset)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
And then simply use `TD(X_CTL)` anywhere in your keymap.
|
|
||||||
|
|
||||||
If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace.
|
|
||||||
|
|
||||||
### 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`.
|
|
||||||
|
|
||||||
Below your layers and custom keycodes, add the following:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// tapdance keycodes
|
|
||||||
enum td_keycodes {
|
|
||||||
ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance.
|
|
||||||
};
|
|
||||||
|
|
||||||
// define a type containing as many tapdance states as you need
|
|
||||||
typedef enum {
|
|
||||||
SINGLE_TAP,
|
|
||||||
SINGLE_HOLD,
|
|
||||||
DOUBLE_SINGLE_TAP
|
|
||||||
} td_state_t;
|
|
||||||
|
|
||||||
// create a global instance of the tapdance state type
|
|
||||||
static td_state_t td_state;
|
|
||||||
|
|
||||||
// declare your tapdance functions:
|
|
||||||
|
|
||||||
// function to determine the current tapdance state
|
|
||||||
int cur_dance (qk_tap_dance_state_t *state);
|
|
||||||
|
|
||||||
// `finished` and `reset` functions for each tapdance keycode
|
|
||||||
void altlp_finished (qk_tap_dance_state_t *state, void *user_data);
|
|
||||||
void altlp_reset (qk_tap_dance_state_t *state, void *user_data);
|
|
||||||
```
|
|
||||||
|
|
||||||
Below your `LAYOUT`, define each of the tapdance functions:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// determine the tapdance state to return
|
|
||||||
int cur_dance (qk_tap_dance_state_t *state) {
|
|
||||||
if (state->count == 1) {
|
|
||||||
if (state->interrupted || !state->pressed) { return SINGLE_TAP; }
|
|
||||||
else { return SINGLE_HOLD; }
|
|
||||||
}
|
|
||||||
if (state->count == 2) { return DOUBLE_SINGLE_TAP; }
|
|
||||||
else { return 3; } // any number higher than the maximum state value you return above
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle the possible states for each tapdance keycode you define:
|
|
||||||
|
|
||||||
void altlp_finished (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
td_state = cur_dance(state);
|
|
||||||
switch (td_state) {
|
|
||||||
case SINGLE_TAP:
|
|
||||||
register_code16(KC_LPRN);
|
|
||||||
break;
|
|
||||||
case SINGLE_HOLD:
|
|
||||||
register_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_on(_MY_LAYER)` here
|
|
||||||
break;
|
|
||||||
case DOUBLE_SINGLE_TAP: // allow nesting of 2 parens `((` within tapping term
|
|
||||||
tap_code16(KC_LPRN);
|
|
||||||
register_code16(KC_LPRN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void altlp_reset (qk_tap_dance_state_t *state, void *user_data) {
|
|
||||||
switch (td_state) {
|
|
||||||
case SINGLE_TAP:
|
|
||||||
unregister_code16(KC_LPRN);
|
|
||||||
break;
|
|
||||||
case SINGLE_HOLD:
|
|
||||||
unregister_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_off(_MY_LAYER)` here
|
|
||||||
break;
|
|
||||||
case DOUBLE_SINGLE_TAP:
|
|
||||||
unregister_code16(KC_LPRN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
|
|
||||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
|
||||||
[ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.
|
|
@ -1,107 +0,0 @@
|
|||||||
# Terminal
|
|
||||||
|
|
||||||
> This feature is currently *huge* at 4400 bytes, and should probably only be put on boards with a lot of memory, or for fun.
|
|
||||||
|
|
||||||
The terminal feature is a command-line-like interface designed to communicate through a text editor with keystrokes. It's beneficial to turn off auto-indent features in your editor.
|
|
||||||
|
|
||||||
To enable, stick this in your `rules.mk` or `Makefile`:
|
|
||||||
|
|
||||||
TERMINAL_ENABLE = yes
|
|
||||||
|
|
||||||
And use the `TERM_ON` and `TERM_OFF` keycodes to turn it on or off.
|
|
||||||
|
|
||||||
When enabled, a `> ` prompt will appear, where you'll be able to type, backspace (a bell will ding if you reach the beginning and audio is enabled), and hit enter to send the command. Arrow keys are currently disabled so it doesn't get confused. Moving your cursor around with the mouse is discouraged.
|
|
||||||
|
|
||||||
`#define TERMINAL_HELP` enables some other output helpers that aren't really needed with this page.
|
|
||||||
|
|
||||||
Pressing "up" and "down" will allow you to cycle through the past 5 commands entered.
|
|
||||||
|
|
||||||
## Future Ideas
|
|
||||||
|
|
||||||
* Keyboard/user-extensible commands
|
|
||||||
* Smaller footprint
|
|
||||||
* Arrow key support
|
|
||||||
* Command history - Done
|
|
||||||
* SD card support
|
|
||||||
* LCD support for buffer display
|
|
||||||
* Keycode -> name string LUT
|
|
||||||
* Layer status
|
|
||||||
* *Analog/digital port read/write*
|
|
||||||
* RGB mode stuff
|
|
||||||
* Macro definitions
|
|
||||||
* EEPROM read/write
|
|
||||||
* Audio control
|
|
||||||
|
|
||||||
## Current Commands
|
|
||||||
|
|
||||||
### `about`
|
|
||||||
|
|
||||||
Prints out the current version of QMK with a build date:
|
|
||||||
|
|
||||||
```
|
|
||||||
> about
|
|
||||||
QMK Firmware
|
|
||||||
v0.5.115-7-g80ed73-dirty
|
|
||||||
Built: 2017-08-29-20:24:44
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### `print-buffer`
|
|
||||||
|
|
||||||
Outputs the last 5 commands entered
|
|
||||||
|
|
||||||
```
|
|
||||||
> print-buffer
|
|
||||||
0. print-buffer
|
|
||||||
1. help
|
|
||||||
2. about
|
|
||||||
3. keymap 0
|
|
||||||
4. help
|
|
||||||
5. flush-buffer
|
|
||||||
```
|
|
||||||
|
|
||||||
### `flush-buffer`
|
|
||||||
|
|
||||||
Clears command buffer
|
|
||||||
```
|
|
||||||
> flush-buffer
|
|
||||||
Buffer cleared!
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### `help`
|
|
||||||
|
|
||||||
|
|
||||||
Prints out the available commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
> help
|
|
||||||
commands available:
|
|
||||||
about help keycode keymap exit print-buffer flush-buffer
|
|
||||||
```
|
|
||||||
|
|
||||||
### `keycode <layer> <row> <col>`
|
|
||||||
|
|
||||||
Prints out the keycode value of a certain layer, row, and column:
|
|
||||||
|
|
||||||
```
|
|
||||||
> keycode 0 1 0
|
|
||||||
0x29 (41)
|
|
||||||
```
|
|
||||||
|
|
||||||
### `keymap <layer>`
|
|
||||||
|
|
||||||
Prints out the entire keymap for a certain layer
|
|
||||||
|
|
||||||
```
|
|
||||||
> keymap 0
|
|
||||||
0x002b, 0x0014, 0x001a, 0x0008, 0x0015, 0x0017, 0x001c, 0x0018, 0x000c, 0x0012, 0x0013, 0x002a,
|
|
||||||
0x0029, 0x0004, 0x0016, 0x0007, 0x0009, 0x000a, 0x000b, 0x000d, 0x000e, 0x000f, 0x0033, 0x0034,
|
|
||||||
0x00e1, 0x001d, 0x001b, 0x0006, 0x0019, 0x0005, 0x0011, 0x0010, 0x0036, 0x0037, 0x0038, 0x0028,
|
|
||||||
0x5cd6, 0x00e0, 0x00e2, 0x00e3, 0x5cd4, 0x002c, 0x002c, 0x5cd5, 0x0050, 0x0051, 0x0052, 0x004f,
|
|
||||||
>
|
|
||||||
```
|
|
||||||
|
|
||||||
### `exit`
|
|
||||||
|
|
||||||
Exits the terminal - same as `TERM_OFF`.
|
|
@ -1,10 +0,0 @@
|
|||||||
# Thermal Printer
|
|
||||||
|
|
||||||
<!-- FIXME: Describe thermal printers support here. -->
|
|
||||||
|
|
||||||
## Thermal Printer Keycodes
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|-----------|----------------------------------------|
|
|
||||||
|`PRINT_ON` |Start printing everything the user types|
|
|
||||||
|`PRINT_OFF`|Stop printing everything the user types |
|
|
@ -1,251 +0,0 @@
|
|||||||
# Userspace: Sharing Code Between Keymaps
|
|
||||||
|
|
||||||
If you use more than one keyboard with a similar keymap, you might see the benefit in being able to share code between them. Create your own folder in `users/` named the same as your keymap (ideally your github username, `<name>`) with the following structure:
|
|
||||||
|
|
||||||
* `/users/<name>/` (added to the path automatically)
|
|
||||||
* `readme.md` (optional, recommended)
|
|
||||||
* `rules.mk` (included automatically)
|
|
||||||
* `config.h` (included automatically)
|
|
||||||
* `<name>.h` (optional)
|
|
||||||
* `<name>.c` (optional)
|
|
||||||
* `cool_rgb_stuff.c` (optional)
|
|
||||||
* `cool_rgb_stuff.h` (optional)
|
|
||||||
|
|
||||||
|
|
||||||
All this only happens when you build a keymap named `<name>`, like this:
|
|
||||||
|
|
||||||
make planck:<name>
|
|
||||||
|
|
||||||
For example,
|
|
||||||
|
|
||||||
make planck:jack
|
|
||||||
|
|
||||||
Will include the `/users/jack/` folder in the path, along with `/users/jack/rules.mk`.
|
|
||||||
|
|
||||||
!> This `name` can be [overridden](#override-default-userspace), if needed.
|
|
||||||
|
|
||||||
## `Rules.mk`
|
|
||||||
|
|
||||||
The `rules.mk` is one of the two files that gets processed automatically. This is how you add additional source files (such as `<name>.c`) will be added when compiling.
|
|
||||||
|
|
||||||
It's highly recommended that you use `<name>.c` as the default source file to be added. And to add it, you need to add it the SRC in `rules.mk` like this:
|
|
||||||
|
|
||||||
SRC += <name>.c
|
|
||||||
|
|
||||||
Additional files may be added in the same way - it's recommended you have one named `<name>`.c/.h to start off with, though.
|
|
||||||
|
|
||||||
The `/users/<name>/rules.mk` file will be included in the build _after_ the `rules.mk` from your keymap. This allows you to have features in your userspace `rules.mk` that depend on individual QMK features that may or may not be available on a specific keyboard.
|
|
||||||
|
|
||||||
For example, if you have RGB control features shared between all your keyboards that support RGB lighting, you can add support for that if the RGBLIGHT feature is enabled:
|
|
||||||
```make
|
|
||||||
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
|
||||||
# Include my fancy rgb functions source here
|
|
||||||
SRC += cool_rgb_stuff.c
|
|
||||||
endif
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can `define RGB_ENABLE` in your keymap's `rules.mk` and then check for the variable in your userspace's `rules.mk` like this:
|
|
||||||
```make
|
|
||||||
ifdef RGB_ENABLE
|
|
||||||
# Include my fancy rgb functions source here
|
|
||||||
SRC += cool_rgb_stuff.c
|
|
||||||
endif
|
|
||||||
```
|
|
||||||
|
|
||||||
### Override default userspace
|
|
||||||
|
|
||||||
By default the userspace used will be the same as the keymap name. In some situations this isn't desirable. For instance, if you use the [layout](feature_layouts.md) feature you can't use the same name for different keymaps (e.g. ANSI and ISO). You can name your layouts `mylayout-ansi` and `mylayout-iso` and add the following line to your layout's `rules.mk`:
|
|
||||||
|
|
||||||
```
|
|
||||||
USER_NAME := mylayout
|
|
||||||
```
|
|
||||||
|
|
||||||
This is also useful if you have multiple different keyboards with different features physically present on the board (such as one with RGB Lights, and one with Audio, or different number of LEDs, or connected to a different PIN on the controller).
|
|
||||||
|
|
||||||
## Configuration Options (`config.h`)
|
|
||||||
|
|
||||||
Additionally, `config.h` here will be processed like the same file in your keymap folder. This is handled separately from the `<name>.h` file.
|
|
||||||
|
|
||||||
The reason for this, is that `<name>.h` won't be added in time to add settings (such as `#define TAPPING_TERM 100`), and including the `<name.h>` file in any `config.h` files will result in compile issues.
|
|
||||||
|
|
||||||
!>You should use the `config.h` for [configuration options](config_options.md), and the `<name>.h` file for user or keymap specific settings (such as the enum for layer or keycodes)
|
|
||||||
|
|
||||||
|
|
||||||
## Readme (`readme.md`)
|
|
||||||
|
|
||||||
Please include authorship (your name, github username, email), and optionally [a license that's GPL compatible](https://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses).
|
|
||||||
|
|
||||||
You can use this as a template:
|
|
||||||
```
|
|
||||||
Copyright <year> <name> <email> @<github_username>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
However, you can actually add support for keymap version, so that you can use it in both your userspace and your keymap!
|
|
||||||
|
|
||||||
|
|
||||||
For instance, lets looks at the `layer_state_set_user` function. Lets enable the [Tri Layer State](ref_functions.md#olkb-tri-layers) functionalitly to all of our boards, and then still have your `keymap.c` still able to use this functionality.
|
|
||||||
|
|
||||||
In your `<name.c>` file, you'd want to add this:
|
|
||||||
```c
|
|
||||||
__attribute__ ((weak))
|
|
||||||
uint32_t layer_state_set_keymap (uint32_t state) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t layer_state_set_user (uint32_t state) {
|
|
||||||
state = update_tri_layer_state(state, 2, 3, 5);
|
|
||||||
return layer_state_set_keymap (state);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
The `__attribute__ ((weak))` part tells the compiler that this is a placeholder function that can then be replaced by a version in your `keymap.c`. That way, you don't need to add it to your `keymap.c`, but if you do, you won't get any conflicts because the function is the same name.
|
|
||||||
|
|
||||||
The `_keymap` part here doesn't matter, it just needs to be something other than `_quantum`, `_kb`, or `_user`, since those are already in use. So you could use `layer_state_set_mine`, `layer_state_set_fn`, or anything else.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
For instance, if you wanted to have a bunch of macros available, but only on certain boards (to save space), you could "hide" them being a `#ifdef MACROS_ENABLED`, and then enable it per board. To do this, add this to your rules.mk
|
|
||||||
```make
|
|
||||||
ifeq ($(strip $(MACROS_ENABLED)), yes)
|
|
||||||
OPT_DEFS += -DMACROS_ENABLED
|
|
||||||
endif
|
|
||||||
```
|
|
||||||
The `OPT_DEFS` setting causes `MACROS_ENABLED` to be defined for your keyboards (note the `-D` in front of the name), and you could use `#ifdef MACROS_ENABLED` to check the status in your c/h files, and handle that code based on that.
|
|
||||||
|
|
||||||
Then you add `MACROS_ENABLED = yes` to the `rules.mk` for you keymap to enable this feature and the code in your userspace.
|
|
||||||
|
|
||||||
And in your `process_record_user` function, you'd do something like this:
|
|
||||||
```c
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
#ifdef MACROS_ENABLED
|
|
||||||
case MACRO1:
|
|
||||||
if (!record->event.pressed) {
|
|
||||||
SEND_STRING("This is macro 1!");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MACRO2:
|
|
||||||
if (!record->event.pressed) {
|
|
||||||
SEND_STRING("This is macro 2!");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
First, you'd want to go through all of your `keymap.c` files and replace `process_record_user` with `process_record_keymap` instead. This way, you can still use keyboard specific codes on those boards, and use your custom "global" keycodes as well. You'll also want to replace `SAFE_RANGE` with `NEW_SAFE_RANGE` so that you wont have any overlapping keycodes
|
|
||||||
|
|
||||||
Then add `#include <name.h>` to all of your keymap.c files. This allows you to use these new keycodes without having to redefine them in each keymap.
|
|
||||||
|
|
||||||
Once you've done that, you'll want to set the keycode definitions that you need to the `<name>.h` file. For instance:
|
|
||||||
```c
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quantum.h"
|
|
||||||
#include "action.h"
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
// Define all of
|
|
||||||
enum custom_keycodes {
|
|
||||||
KC_MAKE = SAFE_RANGE,
|
|
||||||
NEW_SAFE_RANGE //use "NEW_SAFE_RANGE" for keymap specific codes
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you want to create the `<name>.c` file, and add this content to it:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "<name>.h"
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
||||||
switch (keycode) {
|
|
||||||
case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
|
|
||||||
if (!record->event.pressed) {
|
|
||||||
uint8_t temp_mod = get_mods();
|
|
||||||
uint8_t temp_osm = get_oneshot_mods();
|
|
||||||
clear_mods(); clear_oneshot_mods();
|
|
||||||
SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP);
|
|
||||||
#ifndef FLASH_BOOTLOADER
|
|
||||||
if ( (temp_mod | temp_osm) & MOD_MASK_SHIFT )
|
|
||||||
#endif
|
|
||||||
{ //
|
|
||||||
#if defined(__arm__) // only run for ARM boards
|
|
||||||
SEND_STRING(":dfu-util");
|
|
||||||
#elif defined(BOOTLOADER_DFU) // only run for DFU boards
|
|
||||||
SEND_STRING(":dfu");
|
|
||||||
#elif defined(BOOTLOADER_HALFKAY) // only run for teensy boards
|
|
||||||
SEND_STRING(":teensy");
|
|
||||||
#elif defined(BOOTLOADER_CATERINA) // only run for Pro Micros
|
|
||||||
SEND_STRING(":avrdude");
|
|
||||||
#endif // bootloader options
|
|
||||||
}
|
|
||||||
if ( (temp_mod | temp_osm) & MOD_MASK_CTRL) {
|
|
||||||
SEND_STRING(" -j8 --output-sync");
|
|
||||||
}
|
|
||||||
SEND_STRING(SS_TAP(X_ENTER));
|
|
||||||
set_mods(temp_mod);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
return process_record_keymap(keycode, record);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For boards that may not have a shift button (such as on a macro pad), we need a way to always include the bootloader option. To do that, add the following to the `rules.mk` in your userspace folder:
|
|
||||||
|
|
||||||
```make
|
|
||||||
ifeq ($(strip $(FLASH_BOOTLOADER)), yes)
|
|
||||||
OPT_DEFS += -DFLASH_BOOTLOADER
|
|
||||||
endif
|
|
||||||
```
|
|
||||||
|
|
||||||
This will add a new `KC_MAKE` keycode that can be used in any of your keymaps. And this keycode will output `make <keyboard>:<keymap>`, making frequent compiling easier. And this will work with any keyboard and any keymap as it will output the current boards info, so that you don't have to type this out every time.
|
|
||||||
|
|
||||||
Also, holding `shift` will add the appropriate flashing command (`:dfu`, `:teensy`, `:avrdude`, `:dfu-util`) for a majority of keyboards. Holding `control` will add some commands that will speed up compiling time by processing multiple files at once.
|
|
||||||
|
|
||||||
And for the boards that lack a shift key, or that you want to always attempt the flashing part, you can add `FLASH_BOOTLOADER = yes` to the `rules.mk` of that keymap.
|
|
||||||
|
|
||||||
?> This should flash the newly compiled firmware automatically, using the correct utility, based on the bootloader settings (or default to just generating the HEX file). However, it should be noted that this may not work on all systems. AVRDUDE doesn't work on WSL, namely. And this doesn't support BootloadHID or mdloader.
|
|
@ -1,30 +0,0 @@
|
|||||||
# Velocikey
|
|
||||||
|
|
||||||
Velocikey is a feature that lets you control the speed of lighting effects (like the Rainbow Swirl effect) with the speed of your typing. The faster you type, the faster the lights will go!
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
For Velocikey to take effect, there are two steps. First, when compiling your keyboard, you'll need to set `VELOCIKEY_ENABLE=yes` in `rules.mk`, e.g.:
|
|
||||||
|
|
||||||
```
|
|
||||||
BOOTMAGIC_ENABLE = no
|
|
||||||
MOUSEKEY_ENABLE = no
|
|
||||||
STENO_ENABLE = no
|
|
||||||
EXTRAKEY_ENABLE = yes
|
|
||||||
VELOCIKEY_ENABLE = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, while using your keyboard, you need to also turn it on with the VLK_TOG keycode, which toggles the feature on and off.
|
|
||||||
|
|
||||||
The following light effects will all be controlled by Velocikey when it is enabled:
|
|
||||||
- RGB Breathing
|
|
||||||
- RGB Rainbow Mood
|
|
||||||
- RGB Rainbow Swirl
|
|
||||||
- RGB Snake
|
|
||||||
- RGB Knight
|
|
||||||
|
|
||||||
Support for LED breathing effects is planned but not available yet.
|
|
||||||
|
|
||||||
As long as Velocikey is enabled, it will control the speed regardless of any other speed setting that your RGB lights are currently on.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
Velocikey doesn't currently support any configuration via keyboard settings. If you want to adjust something like the speed increase or decay rate, you would need to edit `velocikey.c` and adjust the values there to achieve the kinds of speeds that you like.
|
|
@ -1,35 +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.
|
|
||||||
* [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").
|
|
||||||
* [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.
|
|
||||||
* [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.
|
|
||||||
* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys) - Sticky Keys, lets 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_shift.md) - Use your left/right shift keys to type parenthesis and brackets.
|
|
||||||
* [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.
|
|
@ -1,152 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
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`.
|
|
||||||
|
|
||||||
## DFU
|
|
||||||
|
|
||||||
Atmel's DFU bootloader comes on all atmega32u4 chips by default, and is used by many keyboards that have their own ICs on their PCBs (Older OLKB boards, Clueboards). Some keyboards may also use LUFA's DFU bootloader (or QMK's fork) (Newer OLKB boards) that adds in additional features specific to that hardware.
|
|
||||||
|
|
||||||
To ensure compatibility with the DFU bootloader, make sure this block is present your `rules.mk` (optionally with `lufa-dfu` or `qmk-dfu` instead):
|
|
||||||
|
|
||||||
# Bootloader
|
|
||||||
# This definition is optional, and if your keyboard supports multiple bootloaders of
|
|
||||||
# different sizes, comment this out, and the correct address will be loaded
|
|
||||||
# automatically (+60). See bootloader.mk for all options.
|
|
||||||
BOOTLOADER = atmel-dfu
|
|
||||||
|
|
||||||
Compatible flashers:
|
|
||||||
|
|
||||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
|
||||||
* [dfu-programmer](https://github.com/dfu-programmer/dfu-programmer) / `:dfu` in QMK (recommended command line)
|
|
||||||
* [Atmel's Flip](http://www.microchip.com/developmenttools/productdetails.aspx?partno=flip) (not recommended)
|
|
||||||
|
|
||||||
Flashing sequence:
|
|
||||||
|
|
||||||
1. Press the `RESET` keycode, or tap the RESET button (or short RST to GND).
|
|
||||||
2. Wait for the OS to detect the device
|
|
||||||
3. Erase the memory (may be done automatically)
|
|
||||||
4. Flash a .hex file
|
|
||||||
5. Reset the device into application mode (may be done automatically)
|
|
||||||
|
|
||||||
or:
|
|
||||||
|
|
||||||
make <keyboard>:<keymap>:dfu
|
|
||||||
|
|
||||||
### QMK DFU
|
|
||||||
|
|
||||||
QMK has a fork of the LUFA DFU bootloader that allows for a simple matrix scan for exiting the bootloader and returning to the application, as well as flashing an LED/making a ticking noise with a speaker when things are happening. To enable these features, use this block in your `config.h` (The key that exits the bootloader needs to be hooked-up to the INPUT and OUTPUT defined here):
|
|
||||||
|
|
||||||
#define QMK_ESC_OUTPUT F1 // usually COL
|
|
||||||
#define QMK_ESC_INPUT D5 // usually ROW
|
|
||||||
#define QMK_LED E6
|
|
||||||
#define QMK_SPEAKER C6
|
|
||||||
|
|
||||||
The Manufacturer and Product names are automatically pulled from your `config.h`, and "Bootloader" is added to the product.
|
|
||||||
|
|
||||||
To generate this bootloader, use the `bootloader` target, eg `make planck/rev4:default:bootloader`.
|
|
||||||
|
|
||||||
To generate a production-ready .hex file (containing the application and the bootloader), use the `production` target, eg `make planck/rev4:default:production`.
|
|
||||||
|
|
||||||
### DFU commands
|
|
||||||
|
|
||||||
There are a number of DFU commands that you can use to flash firmware to a DFU device:
|
|
||||||
|
|
||||||
* `:dfu` - This is the normal option and waits until a DFU device is available, and then flashes the firmware. This will check every 5 seconds, to see if a DFU device has appeared.
|
|
||||||
* `:dfu-ee` - This flashes an `eep` file instead of the normal hex. This is uncommon.
|
|
||||||
* `:dfu-split-left` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Left Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._
|
|
||||||
* `:dfu-split-right` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Right Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._
|
|
||||||
|
|
||||||
## Caterina
|
|
||||||
|
|
||||||
Arduino boards and their clones use the [Caterina bootloader](https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/caterina) (any keyboard built with a Pro Micro, or clone), and uses the avr109 protocol to communicate through virtual serial. Bootloaders like [A-Star](https://www.pololu.com/docs/0J61/9) are based on Caterina.
|
|
||||||
|
|
||||||
To ensure compatibility with the Caterina bootloader, make sure this block is present your `rules.mk`:
|
|
||||||
|
|
||||||
# Bootloader
|
|
||||||
# This definition is optional, and if your keyboard supports multiple bootloaders of
|
|
||||||
# different sizes, comment this out, and the correct address will be loaded
|
|
||||||
# automatically (+60). See bootloader.mk for all options.
|
|
||||||
BOOTLOADER = caterina
|
|
||||||
|
|
||||||
Compatible flashers:
|
|
||||||
|
|
||||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
|
||||||
* [avrdude](http://www.nongnu.org/avrdude/) with avr109 / `:avrdude` (recommended command line)
|
|
||||||
* [AVRDUDESS](https://github.com/zkemble/AVRDUDESS)
|
|
||||||
|
|
||||||
Flashing sequence:
|
|
||||||
|
|
||||||
1. Press the `RESET` keycode, or short RST to GND quickly (you only have 7 seconds to flash once it enters)
|
|
||||||
2. Wait for the OS to detect the device
|
|
||||||
3. Flash a .hex file
|
|
||||||
4. Wait for the device to reset automatically
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
make <keyboard>:<keymap>:avrdude
|
|
||||||
|
|
||||||
or if you want to flash multiple boards, use the following command
|
|
||||||
|
|
||||||
make <keyboard>:<keymap>:avrdude-loop
|
|
||||||
|
|
||||||
When you're done flashing boards, you'll need to hit Ctrl + C or whatever the correct keystroke is for your operating system to break the loop.
|
|
||||||
|
|
||||||
|
|
||||||
## Halfkay
|
|
||||||
|
|
||||||
Halfkay is a super-slim protocol developed by PJRC that uses HID, and come on all Teensys (namely the 2.0).
|
|
||||||
|
|
||||||
To ensure compatibility with the Halfkay bootloader, make sure this block is present your `rules.mk`:
|
|
||||||
|
|
||||||
# Bootloader
|
|
||||||
# This definition is optional, and if your keyboard supports multiple bootloaders of
|
|
||||||
# different sizes, comment this out, and the correct address will be loaded
|
|
||||||
# automatically (+60). See bootloader.mk for all options.
|
|
||||||
BOOTLOADER = halfkay
|
|
||||||
|
|
||||||
Compatible flashers:
|
|
||||||
|
|
||||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
|
||||||
* [Teensy Loader](https://www.pjrc.com/teensy/loader.html)
|
|
||||||
* [Teensy Loader Command Line](https://www.pjrc.com/teensy/loader_cli.html) (recommended command line)
|
|
||||||
|
|
||||||
Flashing sequence:
|
|
||||||
|
|
||||||
1. Press the `RESET` keycode, or short RST to GND quickly (you only have 7 seconds to flash once it enters)
|
|
||||||
2. Wait for the OS to detect the device
|
|
||||||
3. Flash a .hex file
|
|
||||||
4. Reset the device into application mode (may be done automatically)
|
|
||||||
|
|
||||||
## STM32
|
|
||||||
|
|
||||||
All STM32 chips come preloaded with a factory bootloader that cannot be modified nor deleted. Some STM32 chips have bootloaders that do not come with USB programming (e.g. STM32F103) but the process is still the same.
|
|
||||||
|
|
||||||
At the moment, no `BOOTLOADER` variable is needed on `rules.mk` for STM32.
|
|
||||||
|
|
||||||
Compatible flashers:
|
|
||||||
|
|
||||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
|
||||||
* [dfu-util](https://github.com/Stefan-Schmidt/dfu-util) / `:dfu-util` (recommended command line)
|
|
||||||
|
|
||||||
Flashing sequence:
|
|
||||||
|
|
||||||
1. Enter the bootloader using any of the following methods:
|
|
||||||
* Tap the `RESET` keycode (may not work on STM32F042 devices)
|
|
||||||
* If a reset circuit is present, tap the RESET button
|
|
||||||
* Otherwise, you need to bridge BOOT0 to VCC (via BOOT0 button or bridge), short RESET to GND (via RESET button or bridge), and then let go of the BOOT0 bridge
|
|
||||||
2. Wait for the OS to detect the device
|
|
||||||
3. Flash a .bin file
|
|
||||||
* You will receive a warning about the DFU signature; Just ignore it
|
|
||||||
4. Reset the device into application mode (may be done automatically)
|
|
||||||
* If you are building from command line (e.g. `make planck/rev6:default:dfu-util`), make sure that `:leave` is passed to the `DFU_ARGS` variable inside your `rules.mk` (e.g. `DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave`) so that your device resets after flashing
|
|
||||||
|
|
||||||
### STM32 Commands
|
|
||||||
|
|
||||||
There are a number of DFU commands that you can use to flash firmware to a STM32 device:
|
|
||||||
|
|
||||||
* `:dfu-util` - The default command for flashing to STM32 devices.
|
|
||||||
* `:dfu-util-wait` - This works like the default command, but it gives you a (configurable) 10 second timeout before it attempts to flash the firmware. You can use `TIME_DELAY=20` from the command line to change the timeout.
|
|
||||||
* Eg: `make <keyboard>:<keymap>:dfu-util TIME_DELAY=5`
|
|
||||||
* `:st-link-cli` - This allows you to flash the firmware via ST-LINK's CLI utility, rather than dfu-util.
|
|
@ -1,50 +0,0 @@
|
|||||||
Atmega32u4 Fuse/Lock Bits for Planck/Atomic/Preonic
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Low Fuse: 0x5E
|
|
||||||
High Fuse: 0x99
|
|
||||||
Extended Fuse: 0xF3
|
|
||||||
Lock Byte: 0xFF
|
|
||||||
|
|
||||||
|
|
||||||
ATMega168P Fuse/Lock Bits
|
|
||||||
=========================
|
|
||||||
This configuration is from usbasploader's Makefile.
|
|
||||||
|
|
||||||
HFUSE 0xD6
|
|
||||||
LFUSE 0xDF
|
|
||||||
EFUSE 0x00
|
|
||||||
LOCK 0x3F(intact)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
|
||||||
# ATMega168P
|
|
||||||
#---------------------------------------------------------------------
|
|
||||||
# Fuse extended byte:
|
|
||||||
# 0x00 = 0 0 0 0 0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
|
|
||||||
# \+/
|
|
||||||
# +------- BOOTSZ (00 = 2k bytes)
|
|
||||||
# Fuse high byte:
|
|
||||||
# 0xd6 = 1 1 0 1 0 1 1 0
|
|
||||||
# ^ ^ ^ ^ ^ \-+-/
|
|
||||||
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V)
|
|
||||||
# | | | | + --------- EESAVE (preserve EEPROM over chip erase)
|
|
||||||
# | | | +-------------- WDTON (if 0: watchdog always on)
|
|
||||||
# | | +---------------- SPIEN (allow serial programming)
|
|
||||||
# | +------------------ DWEN (debug wire enable)
|
|
||||||
# +-------------------- RSTDISBL (reset pin is enabled)
|
|
||||||
# Fuse low byte:
|
|
||||||
# 0xdf = 1 1 0 1 1 1 1 1
|
|
||||||
# ^ ^ \ / \--+--/
|
|
||||||
# | | | +------- CKSEL 3..0 (external >8M crystal)
|
|
||||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
|
|
||||||
# | +------------------ CKOUT (if 0: Clock output enabled)
|
|
||||||
# +-------------------- CKDIV8 (if 0: divide by 8)
|
|
||||||
|
|
||||||
|
|
||||||
# Lock Bits
|
|
||||||
# 0x3f = - - 1 1 1 1 1 1
|
|
||||||
# \ / \-/ \-/
|
|
||||||
# | | +----- LB 2..1 (No memory lock features enabled)
|
|
||||||
# | +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section)
|
|
||||||
# +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section)
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
|||||||
# Installing Build Tools
|
|
||||||
|
|
||||||
This page describes setting up the build environment for QMK. These instructions cover AVR processors (such as the atmega32u4).
|
|
||||||
|
|
||||||
<!-- FIXME: We should have ARM instructions somewhere. -->
|
|
||||||
|
|
||||||
Note: If it is your first time here, Check out the "Complete Newbs guide" instead
|
|
||||||
|
|
||||||
## 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 PX4/homebrew-px4
|
|
||||||
brew update
|
|
||||||
brew install avr-gcc@7
|
|
||||||
brew link --force avr-gcc@7
|
|
||||||
brew install dfu-programmer
|
|
||||||
brew install dfu-util
|
|
||||||
brew install gcc-arm-none-eabi
|
|
||||||
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@7` 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.
|
|
||||||
|
|
||||||
## Windows (Vista and Later) (Deprecated)
|
|
||||||
|
|
||||||
These are the old instructions for Windows Vista and later. We recommend you use [MSYS2 as outlined above](#windows-with-msys2-recommended).
|
|
||||||
|
|
||||||
1. If you have ever installed WinAVR, uninstall it.
|
|
||||||
2. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
|
|
||||||
3. If you are going to flash Infinity based keyboards you will need to install dfu-util, refer to the instructions by [Input Club](https://github.com/kiibohd/controller/wiki/Loading-DFU-Firmware).
|
|
||||||
4. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
|
|
||||||
5. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/qmk/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
|
|
||||||
6. Open the `\util` folder.
|
|
||||||
7. Double-click on the `1-setup-path-win` batch script to run it. You'll need to accept a User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
|
|
||||||
8. Right-click on the `2-setup-environment-win` batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!
|
|
||||||
|
|
||||||
If you have trouble and want to ask for help, it is useful to generate a *Win_Check_Output.txt* file by running `Win_Check.bat` in the `\util` folder.
|
|
||||||
|
|
||||||
## 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, the `default` keymap is 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 defaults)
|
|
||||||
```
|
|
||||||
|
|
||||||
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:dfu-util
|
|
||||||
```
|
|
||||||
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).
|
|
@ -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.
|
|
@ -1,59 +0,0 @@
|
|||||||
# How to Use Github with QMK
|
|
||||||
|
|
||||||
Github can be a little tricky to those that aren't familiar with it - this guide will walk through each step of forking, cloning, and submitting a pull request with QMK.
|
|
||||||
|
|
||||||
?> This guide assumes you're somewhat comfortable with running things at the command line, and have git installed on your system.
|
|
||||||
|
|
||||||
Start on the [QMK Github page](https://github.com/qmk/qmk_firmware), and you'll see a button in the upper right that says "Fork":
|
|
||||||
|
|
||||||
![Fork on Github](http://i.imgur.com/8Toomz4.jpg)
|
|
||||||
|
|
||||||
If you're a part of an organization, you'll need to choose which account to fork it to. In most circumstances, you'll want to fork it to your personal account. Once your fork is completed (sometimes this takes a little while), click the "Clone or Download" button:
|
|
||||||
|
|
||||||
![Download from Github](http://i.imgur.com/N1NYcSz.jpg)
|
|
||||||
|
|
||||||
And be sure to select "HTTPS", and select the link and copy it:
|
|
||||||
|
|
||||||
![HTTPS link](http://i.imgur.com/eGO0ohO.jpg)
|
|
||||||
|
|
||||||
From here, enter `git clone ` into the command line, and then paste your link:
|
|
||||||
|
|
||||||
```
|
|
||||||
user@computer:~$ git clone https://github.com/whoeveryouare/qmk_firmware.git
|
|
||||||
Cloning into 'qmk_firmware'...
|
|
||||||
remote: Counting objects: 46625, done.
|
|
||||||
remote: Compressing objects: 100% (2/2), done.
|
|
||||||
remote: Total 46625 (delta 0), reused 0 (delta 0), pack-reused 46623
|
|
||||||
Receiving objects: 100% (46625/46625), 84.47 MiB | 3.14 MiB/s, done.
|
|
||||||
Resolving deltas: 100% (29362/29362), done.
|
|
||||||
Checking out files: 100% (2799/2799), done.
|
|
||||||
```
|
|
||||||
|
|
||||||
You now have your QMK fork on your local machine, and you can add your keymap, compile it and flash it to your board. Once you're happy with your changes, you can add, commit, and push them to your fork like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
user@computer:~$ git add .
|
|
||||||
user@computer:~$ git commit -m "adding my keymap"
|
|
||||||
[master cccb1608] adding my keymap
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
create mode 100644 keyboards/planck/keymaps/mine/keymap.c
|
|
||||||
user@computer:~$ git push
|
|
||||||
Counting objects: 1, done.
|
|
||||||
Delta compression using up to 4 threads.
|
|
||||||
Compressing objects: 100% (1/1), done.
|
|
||||||
Writing objects: 100% (1/1), 1.64 KiB | 0 bytes/s, done.
|
|
||||||
Total 1 (delta 1), reused 0 (delta 0)
|
|
||||||
remote: Resolving deltas: 100% (1/1), completed with 1 local objects.
|
|
||||||
To https://github.com/whoeveryouare/qmk_firmware.git
|
|
||||||
+ 20043e64...7da94ac5 master -> master
|
|
||||||
```
|
|
||||||
|
|
||||||
Your changes now exist on your fork on Github - if you go back there (`https://github.com/<whoeveryouare>/qmk_firmware`), you can create a "New Pull Request" by clicking this button:
|
|
||||||
|
|
||||||
![New Pull Request](http://i.imgur.com/DxMHpJ8.jpg)
|
|
||||||
|
|
||||||
Here you'll be able to see exactly what you've committed - if it all looks good, you can finalize it by clicking "Create Pull Request":
|
|
||||||
|
|
||||||
![Create Pull Request](http://i.imgur.com/Ojydlaj.jpg)
|
|
||||||
|
|
||||||
After submitting, we may talk to you about your changes, ask that you make changes, and eventually accept it! Thanks for contributing to QMK :)
|
|
@ -1,54 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
This page attempts to explain the basic information you need to know to work with the QMK project. It assumes that you are familiar with navigating a Unix shell, but does not assume you are familiar with C or with compiling using make.
|
|
||||||
|
|
||||||
## Basic QMK Structure
|
|
||||||
|
|
||||||
QMK is a fork of [Jun Wako](https://github.com/tmk)'s [tmk_keyboard](https://github.com/tmk/tmk_keyboard) project. The original TMK code, with modifications, can be found in the `tmk` folder. The QMK additions to the project may be found in the `quantum` folder. Keyboard projects may be found in the `handwired` and `keyboard` folders.
|
|
||||||
|
|
||||||
### Userspace Structure
|
|
||||||
|
|
||||||
Within the folder `users` is a directory for each user. This is a place for users to put code that they might use between keyboards. See the docs for [Userspace feature](feature_userspace.md) for more information.
|
|
||||||
|
|
||||||
### Keyboard Project Structure
|
|
||||||
|
|
||||||
Within the folder `keyboards` and its subfolder `handwired` is a directory for each keyboard project, for example `qmk_firmware/keyboards/clueboard`. Within it you'll find the following structure:
|
|
||||||
|
|
||||||
* `keymaps/`: Different keymaps that can be built
|
|
||||||
* `rules.mk`: The file that sets the default "make" options. Do not edit this file directly, instead use a keymap specific `rules.mk`.
|
|
||||||
* `config.h`: The file that sets the default compile time options. Do not edit this file directly, instead use a keymap specific `config.h`.
|
|
||||||
|
|
||||||
### Keymap Structure
|
|
||||||
|
|
||||||
In every keymap folder, the following files may be found. Only `keymap.c` is required, and if the rest of the files are not found the default options will be chosen.
|
|
||||||
|
|
||||||
* `config.h`: the options to configure your keymap
|
|
||||||
* `keymap.c`: all of your keymap code, required
|
|
||||||
* `rules.mk`: the features of QMK that are enabled
|
|
||||||
* `readme.md`: a description of your keymap, how others might use it, and explanations of features. Please upload images to a service like imgur.
|
|
||||||
|
|
||||||
# The `config.h` File
|
|
||||||
|
|
||||||
There are 3 possible `config.h` locations:
|
|
||||||
|
|
||||||
* keyboard (`/keyboards/<keyboard>/config.h`)
|
|
||||||
* userspace (`/users/<user>/config.h`)
|
|
||||||
* keymap (`/keyboards/<keyboard>/keymaps/<keymap>/config.h`)
|
|
||||||
|
|
||||||
The build system automatically picks up the config files in the above order. If you wish to override any setting set by a previous `config.h` you will need to first include some boilerplate code for the settings you wish to change.
|
|
||||||
|
|
||||||
```
|
|
||||||
#pragma once
|
|
||||||
```
|
|
||||||
|
|
||||||
Then to override a setting from the previous `config.h` file you must `#undef` and then `#define` the setting again.
|
|
||||||
|
|
||||||
The boilerplate code and setting look like this together:
|
|
||||||
|
|
||||||
```
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// overrides go here!
|
|
||||||
#undef MY_SETTING
|
|
||||||
#define MY_SETTING 4
|
|
||||||
```
|
|
@ -1,154 +0,0 @@
|
|||||||
# More Detailed `make` Instructions
|
|
||||||
|
|
||||||
The full syntax of the `make` command is `<keyboard_folder>:<keymap>:<target>`, where:
|
|
||||||
|
|
||||||
* `<keyboard_folder>` is the path of the keyboard, for example `planck`
|
|
||||||
* Use `all` to compile all keyboards
|
|
||||||
* Specify the path to compile a revision, for example `planck/rev4` or `planck/rev3`
|
|
||||||
* If the keyboard doesn't have any folders, it can be left out
|
|
||||||
* To compile the default folder, you can leave it out
|
|
||||||
* `<keymap>` is the name of the keymap, for example `algernon`
|
|
||||||
* Use `all` to compile all keymaps
|
|
||||||
* `<target>` will be explained in more detail below.
|
|
||||||
|
|
||||||
The `<target>` means the following
|
|
||||||
* If no target is given, then it's the same as `all` below
|
|
||||||
* `all` compiles as many keyboard/revision/keymap combinations as specified. For example, `make planck/rev4:default` will generate a single .hex, while `make planck/rev4:all` will generate a hex for every keymap available to the planck.
|
|
||||||
* `dfu`, `teensy`, `avrdude` or `dfu-util`, compile and upload the firmware to the keyboard. If the compilation fails, then nothing will be uploaded. The programmer to use depends on the keyboard. For most keyboards it's `dfu`, but for ChibiOS keyboards you should use `dfu-util`, and `teensy` for standard Teensys. To find out which command you should use for your keyboard, check the keyboard specific readme.
|
|
||||||
* **Note**: some operating systems need root access for these commands to work, so in that case you need to run for example `sudo make planck/rev4:default:dfu`.
|
|
||||||
* `clean`, cleans the build output folders to make sure that everything is built from scratch. Run this before normal compilation if you have some unexplainable problems.
|
|
||||||
|
|
||||||
You can also add extra options at the end of the make command line, after the target
|
|
||||||
|
|
||||||
* `make COLOR=false` - turns off color output
|
|
||||||
* `make SILENT=true` - turns off output besides errors/warnings
|
|
||||||
* `make VERBOSE=true` - outputs all of the gcc stuff (not interesting, unless you need to debug)
|
|
||||||
* `make EXTRAFLAGS=-E` - Preprocess the code without doing any compiling (useful if you are trying to debug #define commands)
|
|
||||||
|
|
||||||
The make command itself also has some additional options, type `make --help` for more information. The most useful is probably `-jx`, which specifies that you want to compile using more than one CPU, the `x` represents the number of CPUs that you want to use. Setting that can greatly reduce the compile times, especially if you are compiling many keyboards/keymaps. I usually set it to one less than the number of CPUs that I have, so that I have some left for doing other things while it's compiling. Note that not all operating systems and make versions supports that option.
|
|
||||||
|
|
||||||
Here are some examples commands
|
|
||||||
|
|
||||||
* `make all:all` builds everything (all keyboard folders, all keymaps). Running just `make` from the `root` will also run this.
|
|
||||||
* `make ergodox_infinity:algernon:clean` will clean the build output of the Ergodox Infinity keyboard.
|
|
||||||
* `make planck/rev4:default:dfu COLOR=false` builds and uploads the keymap without color output.
|
|
||||||
|
|
||||||
## `rules.mk` Options
|
|
||||||
|
|
||||||
Set these variables to `no` to disable them, and `yes` to enable them.
|
|
||||||
|
|
||||||
`BOOTMAGIC_ENABLE`
|
|
||||||
|
|
||||||
This allows you to hold a key and the salt key (space by default) and have access to a various EEPROM settings that persist over power loss. It's advised you keep this disabled, as the settings are often changed by accident, and produce confusing results that makes it difficult to debug. It's one of the more common problems encountered in help sessions.
|
|
||||||
|
|
||||||
Consumes about 1000 bytes.
|
|
||||||
|
|
||||||
`MOUSEKEY_ENABLE`
|
|
||||||
|
|
||||||
This gives you control over cursor movements and clicks via keycodes/custom functions.
|
|
||||||
|
|
||||||
`EXTRAKEY_ENABLE`
|
|
||||||
|
|
||||||
This allows you to use the system and audio control key codes.
|
|
||||||
|
|
||||||
`CONSOLE_ENABLE`
|
|
||||||
|
|
||||||
This allows you to print messages that can be read using [`hid_listen`](https://www.pjrc.com/teensy/hid_listen.html).
|
|
||||||
|
|
||||||
By default, all debug (*dprint*) print (*print*, *xprintf*), and user print (*uprint*) messages will be enabled. This will eat up a significant portion of the flash and may make the keyboard .hex file too big to program.
|
|
||||||
|
|
||||||
To disable debug messages (*dprint*) and reduce the .hex file size, include `#define NO_DEBUG` in your `config.h` file.
|
|
||||||
|
|
||||||
To disable print messages (*print*, *xprintf*) and user print messages (*uprint*) and reduce the .hex file size, include `#define NO_PRINT` in your `config.h` file.
|
|
||||||
|
|
||||||
To disable print messages (*print*, *xprintf*) and **KEEP** user print messages (*uprint*), include `#define USER_PRINT` in your `config.h` file.
|
|
||||||
|
|
||||||
To see the text, open `hid_listen` and enjoy looking at your printed messages.
|
|
||||||
|
|
||||||
**NOTE:** Do not include *uprint* messages in anything other than your keymap code. It must not be used within the QMK system framework. Otherwise, you will bloat other people's .hex files.
|
|
||||||
|
|
||||||
Consumes about 400 bytes.
|
|
||||||
|
|
||||||
`COMMAND_ENABLE`
|
|
||||||
|
|
||||||
This enables magic commands, typically fired with the default magic key combo `LSHIFT+RSHIFT+KEY`. Magic commands include turning on debugging messages (`MAGIC+D`) or temporarily toggling NKRO (`MAGIC+N`).
|
|
||||||
|
|
||||||
`SLEEP_LED_ENABLE`
|
|
||||||
|
|
||||||
Enables your LED to breath while your computer is sleeping. Timer1 is being used here. This feature is largely unused and untested, and needs updating/abstracting.
|
|
||||||
|
|
||||||
`NKRO_ENABLE`
|
|
||||||
|
|
||||||
This allows the keyboard to tell the host OS that up to 248 keys are held down at once (default without NKRO is 6). NKRO is off by default, even if `NKRO_ENABLE` is set. NKRO can be forced by adding `#define FORCE_NKRO` to your config.h or by binding `MAGIC_TOGGLE_NKRO` to a key and then hitting the key.
|
|
||||||
|
|
||||||
`BACKLIGHT_ENABLE`
|
|
||||||
|
|
||||||
This enables your backlight on Timer1 and ports B5, B6, or B7 (for now). You can specify your port by putting this in your `config.h`:
|
|
||||||
|
|
||||||
#define BACKLIGHT_PIN B7
|
|
||||||
|
|
||||||
`MIDI_ENABLE`
|
|
||||||
|
|
||||||
This enables MIDI sending and receiving with your keyboard. To enter MIDI send mode, you can use the keycode `MI_ON`, and `MI_OFF` to turn it off. This is a largely untested feature, but more information can be found in the `quantum/quantum.c` file.
|
|
||||||
|
|
||||||
`UNICODE_ENABLE`
|
|
||||||
|
|
||||||
This allows you to send Unicode characters using `UC(<code point>)` in your keymap. Code points up to `0x7FFF` are supported. This covers characters for most modern languages, as well as symbols, but it doesn't cover emoji.
|
|
||||||
|
|
||||||
`UNICODEMAP_ENABLE`
|
|
||||||
|
|
||||||
This allows you to send Unicode characters using `X(<map index>)` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
|
|
||||||
|
|
||||||
`UCIS_ENABLE`
|
|
||||||
|
|
||||||
This allows you to send Unicode characters by inputting a mnemonic corresponding to the character you want to send. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported.
|
|
||||||
|
|
||||||
For further details, as well as limitations, see the [Unicode page](feature_unicode.md).
|
|
||||||
|
|
||||||
`BLUETOOTH_ENABLE`
|
|
||||||
|
|
||||||
This allows you to interface with a Bluefruit EZ-key to send keycodes wirelessly. It uses the D2 and D3 pins.
|
|
||||||
|
|
||||||
`AUDIO_ENABLE`
|
|
||||||
|
|
||||||
This allows you output audio on the C6 pin (needs abstracting). See the [audio page](feature_audio.md) for more information.
|
|
||||||
|
|
||||||
`FAUXCLICKY_ENABLE`
|
|
||||||
|
|
||||||
Uses buzzer to emulate clicky switches. A cheap imitation of the Cherry blue switches. By default, uses the C6 pin, same as `AUDIO_ENABLE`.
|
|
||||||
|
|
||||||
`VARIABLE_TRACE`
|
|
||||||
|
|
||||||
Use this to debug changes to variable values, see the [tracing variables](unit_testing.md#tracing-variables) section of the Unit Testing page for more information.
|
|
||||||
|
|
||||||
`API_SYSEX_ENABLE`
|
|
||||||
|
|
||||||
This enables using the Quantum SYSEX API to send strings (somewhere?)
|
|
||||||
|
|
||||||
This consumes about 5390 bytes.
|
|
||||||
|
|
||||||
`KEY_LOCK_ENABLE`
|
|
||||||
|
|
||||||
This enables [key lock](feature_key_lock.md). This consumes an additional 260 bytes.
|
|
||||||
|
|
||||||
`SPLIT_KEYBOARD`
|
|
||||||
|
|
||||||
This enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
|
|
||||||
|
|
||||||
`SPLIT_TRANSPORT`
|
|
||||||
|
|
||||||
As there is no standard split communication driver for ARM-based split keyboards yet, `SPLIT_TRANSPORT = custom` must be used for these. It will prevent the standard split keyboard communication code (which is AVR-specific) from being included, allowing a custom implementation to be used.
|
|
||||||
|
|
||||||
`CUSTOM_MATRIX`
|
|
||||||
|
|
||||||
Lets you replace the default matrix scanning routine with your own code. You will need to provide your own implementations of matrix_init() and matrix_scan().
|
|
||||||
|
|
||||||
`DEBOUNCE_TYPE`
|
|
||||||
|
|
||||||
Lets you replace the default key debouncing routine with an alternative one. If `custom` you will need to provide your own implementation.
|
|
||||||
|
|
||||||
## Customizing Makefile Options on a Per-Keymap Basis
|
|
||||||
|
|
||||||
If your keymap directory has a file called `rules.mk` any options you set in that file will take precedence over other `rules.mk` options for your particular keyboard.
|
|
||||||
|
|
||||||
So let's say your keyboard's `rules.mk` has `BACKLIGHT_ENABLE = yes`. You want your particular keyboard to not have the backlight, so you make a file called `rules.mk` and specify `BACKLIGHT_ENABLE = no`.
|
|
@ -1,21 +0,0 @@
|
|||||||
# Vagrant Quick Start
|
|
||||||
|
|
||||||
This project includes a Vagrantfile that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
Using the `/Vagrantfile` in this repository requires you have [Vagrant](http://www.vagrantup.com/) as well as [VirtualBox](https://www.virtualbox.org/) (or [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](http://www.vagrantup.com/vmware) but the (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion).
|
|
||||||
|
|
||||||
*COMPATIBILITY NOTICE* Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12. **Alternately, you can try running the following command:** `vagrant plugin install vagrant-vbguest`
|
|
||||||
|
|
||||||
Other than having Vagrant and Virtualbox installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start a Linux virtual machine that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
|
|
||||||
|
|
||||||
# Flashing the Firmware
|
|
||||||
|
|
||||||
The "easy" way to flash the firmware is using a tool from your host OS:
|
|
||||||
|
|
||||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox) (recommended)
|
|
||||||
* [Teensy Loader](https://www.pjrc.com/teensy/loader.html)
|
|
||||||
* [Atmel FLIP](http://www.atmel.com/tools/flip.aspx)
|
|
||||||
|
|
||||||
If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.
|
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 793 B |
@ -1,338 +0,0 @@
|
|||||||
# Quantum Hand-Wiring Guide
|
|
||||||
|
|
||||||
Parts list:
|
|
||||||
* *x* keyswitches (MX, Matias, Gateron, etc)
|
|
||||||
* *x* diodes
|
|
||||||
* Keyboard plate (metal, plastic, cardboard, etc)
|
|
||||||
* Wire (strained for wiring to the Teensy, anything for the rows/columns)
|
|
||||||
* Soldering iron set at 600ºF or 315ºC (if temperature-controlled)
|
|
||||||
* Rosin-cored solder (leaded or lead-free)
|
|
||||||
* Adequate ventilation/a fan
|
|
||||||
* Tweezers (optional)
|
|
||||||
* Wire cutters/snippers
|
|
||||||
|
|
||||||
## How the Matrix Works (Why We Need Diodes)
|
|
||||||
|
|
||||||
The microcontroller (in this case, the Teensy 2.0) 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.
|
|
||||||
|
|
||||||
# The Actual Hand-Wiring
|
|
||||||
|
|
||||||
## Getting Things in Place
|
|
||||||
|
|
||||||
When starting this, you should have all of your stabilisers and keyswitches already installed (and optionally keycaps). If you're using a Cherry-type stabiliser (plate-mounted only, obviously), you'll need to install that before your keyswitches. If you're using Costar ones, you can installed them afterwards.
|
|
||||||
|
|
||||||
To make things easier on yourself, make sure all of the keyswitches are oriented the same way (if they can be - not all layouts support this). Despite this, it's important to remember that the contacts on the keyswitches are completely symmetrical. We'll be using the keyswitch's left side contact for wiring the rows, and the right side one for wiring the columns.
|
|
||||||
|
|
||||||
Get your soldering iron heated-up and collect the rest of the materials from the part list at the beginning of the guide. Place your keyboard so that the bottoms of the keyswitches are accessible - it may be a good idea to place it on a cloth to protect your keyswitches/keycaps.
|
|
||||||
|
|
||||||
Before continuing, plan out where you're going to place your Teensy. If you're working with a board that has a large (6.25u) spacebar, it may be a good idea to place it in-between switches against the plate. Otherwise, you may want to trim some of the leads on the keyswitches where you plan on putting it - this will make it a little harder to solder the wire/diodes, but give you more room to place the Teensy.
|
|
||||||
|
|
||||||
## Preparing the Diodes
|
|
||||||
|
|
||||||
It's a little easier to solder the diodes in place if you bend them at a 90º angle immediately after the black line - this will help to make sure you put them on the right way (direction matters), and in the correct position. The diodes will look like this when bent (with longer leads):
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────┬─┐
|
|
||||||
───┤ │ ├─┐
|
|
||||||
└─────┴─┘ │
|
|
||||||
│
|
|
||||||
```
|
|
||||||
|
|
||||||
We'll be using the long lead at the bent end to connect it to the elbow (bent part) of the next diode, creating the row.
|
|
||||||
|
|
||||||
## 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 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
|
|
||||||
├─┤
|
|
||||||
└┬┘
|
|
||||||
└─────────────
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
The smoke that the rosin releases is harmful, so be careful not to breath it or get it in your eyes/face.
|
|
||||||
|
|
||||||
After soldering things in place, it may be helpful to blow on the joint to push the smoke away from your face, and cool the solder quicker. You should see the solder develop a matte (not shiny) surface as it solidifies. Keep in mind that it will still be very hot afterwards, and will take a couple minutes to be cool to touch. Blow on it will accelerate this process.
|
|
||||||
|
|
||||||
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
|
|
||||||
├─┤ ├─┤
|
|
||||||
└┬┘ └┬┘
|
|
||||||
└────────────────┴─────────────
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
If you're using stranded wire, it's probably easiest to just use a lot of small wires to connect each keyswitch along the column. It's possible to use one and melt through the insulation, but this isn't recommended, will produce even more harmful fumes, and can ruin your soldering iron.
|
|
||||||
|
|
||||||
Before beginning to solder, it helps to have your wire pre-bent (if using single-cored), or at least have an idea of how you're going to route the column (especially if you're making a staggered board). Where you go in particular doesn't matter too much, as we'll be basing our keymap definitions on how it was wired - just make sure every key in a particular row is in a unique column, and that they're in order from left to right.
|
|
||||||
|
|
||||||
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 Things to the Teensy
|
|
||||||
|
|
||||||
Now that the matrix itself is complete, it's time to connect what you've done to the Teensy. You'll be needing the number of pins equal to your number of columns + your number of rows. 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 are: GND, VCC, AREF, and RST - all the others are usable and accessible in the firmware.
|
|
||||||
|
|
||||||
Place the Teensy where you plan to put it - you'll have to cut wires to length in the next step, and you'll want to make sure they reach.
|
|
||||||
|
|
||||||
Starting with the first column on the right side, measure out how much wire you'll need to connect it to the first pin on the Teensy - it helps to pick a side that you'll be able to work down, to keep the wires from overlapping too much. It may help to leave a little bit of slack so things aren't too tight. Cut the piece of wire, and solder it to the Teensy, and then the column - you can solder it anywhere along the column, but it may be easiest at the keyswitch. Just be sure the wire doesn't separate from the keyswitch when soldering.
|
|
||||||
|
|
||||||
As you move from column to column, it'll be helpful to write the locations of the pins down. We'll use this data to setup the matrix in the future.
|
|
||||||
|
|
||||||
When you're done with the columns, start with the rows in the same process, from top to bottom, and write them all down. Again, 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.
|
|
||||||
|
|
||||||
As you move along, be sure that the Teensy is staying in place - recutting and soldering the wires is a pain!
|
|
||||||
|
|
||||||
## Additional guides
|
|
||||||
|
|
||||||
If you're more of a visual learner, or want some additional tips and something more to follow along, these two visual step by step guides may be helpful:
|
|
||||||
|
|
||||||
- [BrownFox's step by step guide](https://deskthority.net/viewtopic.php?f=7&t=6050)
|
|
||||||
- [Cribbit's modern hand wiring guide](https://geekhack.org/index.php?topic=87689.0)
|
|
||||||
|
|
||||||
# Getting Some Basic Firmware Set Up
|
|
||||||
|
|
||||||
From here, you should have a working keyboard once you program a firmware. Before we attach the Teensy permanently to the keyboard, let's quickly get some firmware loaded onto the Teensy so we can test each keyswitch.
|
|
||||||
|
|
||||||
To start out, download [the firmware](https://github.com/qmk/qmk_firmware/) - we'll be using my (Jack's) fork of TMK called QMK/Quantum. 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 project using the script in the root directory of the firmware. In your terminal, run this command with `<project_name>` replaced by the name of your project - it'll need to be different from any other project in the `keyboards/` folder:
|
|
||||||
|
|
||||||
```
|
|
||||||
util/new_project.sh <project_name>
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll want to navigate to the `keyboards/<project_name>/` folder by typing, like the print-out from the script specifies:
|
|
||||||
|
|
||||||
cd keyboards/<project_name>
|
|
||||||
|
|
||||||
### `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).
|
|
||||||
|
|
||||||
### `<project_name>.h`
|
|
||||||
|
|
||||||
The next file you'll want to look at is `<project_name>.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 }, \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
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/<variant>/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/<keyboard>:<variant>`, which will pull `keymaps/<variant>/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 `<project_name>.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 `<project_name>.hex` file, open up the Teensy loader application, and click the file icon. From here, navigate to your `QMK/keyboards/<project_name>/` folder, and select the `<project_name>.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!
|
|
||||||
|
|
||||||
## Testing Your Firmware
|
|
||||||
|
|
||||||
Carefully flip your keyboard over, open up a new text document, and try typing - you should get the characters that you put into your keymap. Test each key, and note 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 <project_name>.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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
# Securing the Teensy, Finishing Your Hardware, Getting Fancier Firmware
|
|
||||||
|
|
||||||
Now that you have a working board, it's time to get things in their permanent positions. I've often used liberal amounts of hot glue to secure and insulate things, so if that's your style, start spreading that stuff like butter. Otherwise, double-sided tape is always an elegant solution, and electrical tape is a distant second. Due to the nature of these builds, a lot of this part is up to you and how you planned (or didn't plan) things out.
|
|
||||||
|
|
||||||
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 project (Planck, Clueboard, Ergodox EZ, etc) to see how people use all of them. You can always stop by [the OLKB subreddit for help!](http://reddit.com/r/olkb)
|
|
@ -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)
|
|
@ -1,153 +0,0 @@
|
|||||||
# Keyboards with AVR Processors
|
|
||||||
|
|
||||||
This page describes the support for for AVR processors in QMK. AVR processors include the atmega32u4, atmega32u2, at90usb1286, and other processors from Atmel Corporation. AVR processors are 8-bit MCU's that are designed to be easy to work with. The most common AVR processors in keyboards have on-board USB and plenty of GPIO for supporting large keyboard matrices. They are the most popular MCU for use in keyboards today.
|
|
||||||
|
|
||||||
If you have not yet you should read the [Keyboard Guidelines](hardware_keyboard_guidelines.md) to get a sense of how keyboards fit into QMK.
|
|
||||||
|
|
||||||
## Adding Your AVR Keyboard to QMK
|
|
||||||
|
|
||||||
QMK has a number of features to simplify working with AVR keyboards. For most keyboards you don't have to write a single line of code. To get started run the `util/new_project.sh` script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ util/new_project.sh my_awesome_keyboard
|
|
||||||
######################################################
|
|
||||||
# /keyboards/my_awesome_keyboard project created. To start
|
|
||||||
# working on things, cd into keyboards/my_awesome_keyboard
|
|
||||||
######################################################
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create all the files needed to support your new keyboard, and populate the settings with default values. Now you just need to customize it for your keyboard.
|
|
||||||
|
|
||||||
## `readme.md`
|
|
||||||
|
|
||||||
This is where you'll describe your keyboard. Please follow the [Keyboard Readme Template](documentation_templates.md#keyboard-readmemd-template) when writing your `readme.md`. You're encouraged to place an image at the top of your `readme.md`, please use an external service such as [Imgur](http://imgur.com) to host the images.
|
|
||||||
|
|
||||||
## `<keyboard>.c`
|
|
||||||
|
|
||||||
This is where all the custom logic for your keyboard goes. Many keyboards do not need to put anything at all in here. You can learn more about writing custom logic in [Custom Quantum Functions](custom_quantum_functions.md).
|
|
||||||
|
|
||||||
## `<keyboard>.h`
|
|
||||||
|
|
||||||
This is the file you define your [Layout Macro(s)](feature_layouts.md) in. At minimum you should have a `#define LAYOUT` for your keyboard that looks something like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define LAYOUT( \
|
|
||||||
k00, k01, k02, \
|
|
||||||
k10, k11 \
|
|
||||||
) { \
|
|
||||||
{ k00, k01, k02 }, \
|
|
||||||
{ k10, KC_NO, k11 }, \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The first half of the `LAYOUT` pre-processor macro defines the physical arrangement of keys. The second half of the macro defines the matrix the switches are connected to. This allows you to have a physical arrangement of keys that differs from the wiring matrix.
|
|
||||||
|
|
||||||
Each of the `k__` variables needs to be unique, and typically they follow the format `k<row><col>`.
|
|
||||||
|
|
||||||
The physical matrix (the second half) must have a number of rows equaling `MATRIX_ROWS`, and each row must have exactly `MATRIX_COLS` elements in it. If you do not have this many physical keys you can use `KC_NO` to fill in the blank spots.
|
|
||||||
|
|
||||||
## `config.h`
|
|
||||||
|
|
||||||
The `config.h` file is where you configure the hardware and feature set for your keyboard. There are a lot of options that can be placed in that file, too many to list there. For a complete overview of available options see the [Config Options](config_options.md) page.
|
|
||||||
|
|
||||||
### Hardware Configuration
|
|
||||||
|
|
||||||
|
|
||||||
At the top of the `config.h` you'll find USB related settings. These control how your keyboard appears to the Operating System. If you don't have a good reason to change you should leave the `VENDOR_ID` as `0xFEED`. For the `PRODUCT_ID` you should pick a number that is not yet in use.
|
|
||||||
|
|
||||||
Do change the `MANUFACTURER`, `PRODUCT`, and `DESCRIPTION` lines to accurately reflect your keyboard.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define VENDOR_ID 0xFEED
|
|
||||||
#define PRODUCT_ID 0x6060
|
|
||||||
#define DEVICE_VER 0x0001
|
|
||||||
#define MANUFACTURER You
|
|
||||||
#define PRODUCT my_awesome_keyboard
|
|
||||||
#define DESCRIPTION A custom keyboard
|
|
||||||
```
|
|
||||||
|
|
||||||
?> Note: On Windows and macOS the `MANUFACTURER`, `PRODUCT`, and `DESCRIPTION` fields will be displayed in the list of USB devices. ?> On Linux these values will not be visible in lsusb by default, since Linux takes the information from the list maintained by [USB ID Repository](http://www.linux-usb.org/usb-ids.html) by default. lsusb will show the information reported by the device when executed with -v option. It is also present in kernel logs after plugging in the device.
|
|
||||||
|
|
||||||
### Keyboard Matrix Configuration
|
|
||||||
|
|
||||||
The next section of the `config.h` file deals with your keyboard's matrix. The first thing you should set is the matrix's size. This is usually, but not always, the same number of rows and columns as the physical key arrangement.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define MATRIX_ROWS 2
|
|
||||||
#define MATRIX_COLS 3
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you've defined the size of your matrix you need to define which pins on your MCU are connected to rows and columns. To do so simply specify the names of those pins:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define MATRIX_ROW_PINS { D0, D5 }
|
|
||||||
#define MATRIX_COL_PINS { F1, F0, B0 }
|
|
||||||
#define UNUSED_PINS
|
|
||||||
```
|
|
||||||
|
|
||||||
The number of `MATRIX_ROW_PINS` entries must be the same as the number you assigned to `MATRIX_ROWS`, and likewise for `MATRIX_COL_PINS` and `MATRIX_COLS`. You do not have to specify `UNUSED_PINS`, but you can if you want to document what pins are open.
|
|
||||||
|
|
||||||
Finally, you can specify the direction your diodes point. This can be `COL2ROW` or `ROW2COL`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define DIODE_DIRECTION COL2ROW
|
|
||||||
```
|
|
||||||
|
|
||||||
### Backlight Configuration
|
|
||||||
|
|
||||||
By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are using one of those you can simply enable it here. For more details see the [Backlight Documentation](feature_backlight.md).
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define BACKLIGHT_PIN B7
|
|
||||||
#define BACKLIGHT_LEVELS 3
|
|
||||||
#define BACKLIGHT_BREATHING
|
|
||||||
#define BREATHING_PERIOD 6
|
|
||||||
```
|
|
||||||
|
|
||||||
?> You can use backlighting on any pin you like, but you will have to do more work to support that. See the [Backlight Documentation](feature_backlight.md) for more details.
|
|
||||||
|
|
||||||
### Other Configuration Options
|
|
||||||
|
|
||||||
There are a lot of features that can be configured or tuned in `config.h`. You should see the [Config Options](config_options.md) page for more details.
|
|
||||||
|
|
||||||
## `rules.mk`
|
|
||||||
|
|
||||||
You use the `rules.mk` file to tell QMK what files to build and what features to enable. If you are building around an atmega32u4 you can largely leave these defaults alone. If you are using another MCU you may have to tweak some parameters.
|
|
||||||
|
|
||||||
### MCU Options
|
|
||||||
|
|
||||||
These options tell the build system what CPU to build for. Be very careful if you change any of these settings, you can render your keyboard inoperable.
|
|
||||||
|
|
||||||
```make
|
|
||||||
MCU = atmega32u4
|
|
||||||
F_CPU = 16000000
|
|
||||||
ARCH = AVR8
|
|
||||||
F_USB = $(F_CPU)
|
|
||||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
|
||||||
```
|
|
||||||
|
|
||||||
### Bootloaders
|
|
||||||
|
|
||||||
The bootloader is a special section of your MCU that allows you to upgrade the code stored on the MCU. Think of it like a Rescue Partition for your keyboard.
|
|
||||||
|
|
||||||
#### Teensy Bootloader Example
|
|
||||||
|
|
||||||
```make
|
|
||||||
BOOTLOADER = halfkay
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Atmel DFU Loader Example
|
|
||||||
|
|
||||||
```make
|
|
||||||
BOOTLOADER = atmel-dfu
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Pro Micro Bootloader Example
|
|
||||||
|
|
||||||
```make
|
|
||||||
BOOTLOADER = caterina
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build Options
|
|
||||||
|
|
||||||
There are a number of features that can be turned on or off in `rules.mk`. See the [Config Options](config_options.md#feature-options) page for a detailed list and description.
|
|
@ -1,35 +0,0 @@
|
|||||||
# QMK Hardware Drivers
|
|
||||||
|
|
||||||
QMK is used on a lot of different hardware. While support for the most common MCU's and matrix configurations is built-in there are a number of drivers that can be added to a keyboard to support additional hardware. Examples include mice and other pointing devices, i/o expanders for split keyboards, bluetooth modules, and LCD, OLED, and TFT screens.
|
|
||||||
|
|
||||||
<!-- FIXME: This should talk about how drivers are integrated into QMK and how you can add your own driver.
|
|
||||||
|
|
||||||
# Driver System Overview
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
# Available Drivers
|
|
||||||
|
|
||||||
## ProMicro (AVR Only)
|
|
||||||
|
|
||||||
Support for addressing pins on the ProMicro by their Arduino name rather than their AVR name. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
|
|
||||||
|
|
||||||
## SSD1306 (AVR Only)
|
|
||||||
|
|
||||||
Support for SSD1306 based OLED displays. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
|
|
||||||
|
|
||||||
## uGFX
|
|
||||||
|
|
||||||
You can make use of uGFX within QMK to drive character and graphic LCD's, LED arrays, OLED, TFT, and other display technologies. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
|
|
||||||
|
|
||||||
## WS2812 (AVR Only)
|
|
||||||
|
|
||||||
Support for WS2811/WS2812{a,b,c} LED's. For more information see the [RGB Light](feature_rgblight.md) page.
|
|
||||||
|
|
||||||
## IS31FL3731
|
|
||||||
|
|
||||||
Support for up to 2 drivers. Each driver impliments 2 charlieplex matrices to individually address LEDs using I2C. This allows up to 144 same color LEDs or 32 RGB LEDs. For more information on how to setup the driver see the [RGB Matrix](feature_rgb_matrix.md) page.
|
|
||||||
|
|
||||||
## IS31FL3733
|
|
||||||
|
|
||||||
Support for up to a single driver with room for expansion. Each driver can control 192 individual LEDs or 64 RGB LEDs. For more information on how to setup the driver see the [RGB Matrix](feature_rgb_matrix.md) page.
|
|
@ -1,149 +0,0 @@
|
|||||||
# QMK Keyboard Guidelines
|
|
||||||
|
|
||||||
Since starting, QMK has grown by leaps and bounds thanks to people like you who contribute to creating and maintaining our community keyboards. As we've grown we've discovered some patterns that work well, and ask that you conform to them to make it easier for other people to benefit from your hard work.
|
|
||||||
|
|
||||||
|
|
||||||
## Naming Your Keyboard/Project
|
|
||||||
|
|
||||||
All keyboard names are in lower case, consisting only of letters, numbers, and underscore (`_`). Names may not begin with an underscore. Forward slash (`/`) is used as a sub-folder separation character.
|
|
||||||
|
|
||||||
The names `test`, `keyboard`, and `all` are reserved for make commands and may not be used as a keyboard or subfolder name.
|
|
||||||
|
|
||||||
Valid Examples:
|
|
||||||
|
|
||||||
* `412_64`
|
|
||||||
* `chimera_ortho`
|
|
||||||
* `clueboard/66/rev3`
|
|
||||||
* `planck`
|
|
||||||
* `v60_type_r`
|
|
||||||
|
|
||||||
## Sub-folders
|
|
||||||
|
|
||||||
QMK uses sub-folders both for organization and to share code between revisions of the same keyboard. You can nest folders up to 4 levels deep:
|
|
||||||
|
|
||||||
qmk_firmware/keyboards/top_folder/sub_1/sub_2/sub_3/sub_4
|
|
||||||
|
|
||||||
If a sub-folder has a `rules.mk` file it will be considered a compilable keyboard. It will be available in QMK Configurator and tested with `make all`. If you are using a folder to organize several keyboards from the same maker you should not have a `rules.mk` file.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
Clueboard uses sub-folders for both purposes, organization and keyboard revisions.
|
|
||||||
|
|
||||||
* [`qmk_firmware`](https://github.com/qmk/qmk_firmware/tree/master)
|
|
||||||
* [`keyboards`](https://github.com/qmk/qmk_firmware/tree/master/keyboards)
|
|
||||||
* [`clueboard`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard) ← This is the organization folder, there's no `rules.mk` file
|
|
||||||
* [`60`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/60) ← This is a compilable keyboard, it has a `rules.mk` file
|
|
||||||
* [`66`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66) ← This is also compilable- it uses `DEFAULT_FOLDER` to specify `rev3` as the default revision
|
|
||||||
* [`rev1`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev1) ← compilable: `make clueboard/66/rev1`
|
|
||||||
* [`rev2`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev2) ← compilable: `make clueboard/66/rev2`
|
|
||||||
* [`rev3`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev3) ← compilable: `make clueboard/66/rev3` or `make clueboard/66`
|
|
||||||
|
|
||||||
## Keyboard Folder Structure
|
|
||||||
|
|
||||||
Your keyboard should be located in `qmk_firmware/keyboards/` and the folder name should be your keyboard's name as described in the previous section. Inside this folder should be several files:
|
|
||||||
|
|
||||||
* `readme.md`
|
|
||||||
* `info.json`
|
|
||||||
* `config.h`
|
|
||||||
* `rules.mk`
|
|
||||||
* `<keyboard_name>.c`
|
|
||||||
* `<keyboard_name>.h`
|
|
||||||
|
|
||||||
### `readme.md`
|
|
||||||
|
|
||||||
All projects need to have a `readme.md` file that explains what the keyboard is, who made it and where it's available. If applicable, it should also contain links to more information, such as the maker's website. Please follow the [published template](documentation_templates.md#keyboard-readmemd-template).
|
|
||||||
|
|
||||||
### `info.json`
|
|
||||||
|
|
||||||
This file is used by the [QMK API](https://github.com/qmk/qmk_api). It contains the information [QMK Configurator](https://config.qmk.fm/) needs to display a representation of your keyboard. You can also set metadata here. For more information see the [reference page](reference_info_json.md).
|
|
||||||
|
|
||||||
### `config.h`
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
### `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.
|
|
||||||
|
|
||||||
### `<keyboard_name.c>`
|
|
||||||
|
|
||||||
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 auxillary hardware this file can be blank.
|
|
||||||
|
|
||||||
The following functions are typically defined in this file:
|
|
||||||
|
|
||||||
* `void matrix_init_kb(void)`
|
|
||||||
* `void matrix_scan_kb(void)`
|
|
||||||
* `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
|
|
||||||
* `void led_set_kb(uint8_t usb_led)`
|
|
||||||
|
|
||||||
### `<keyboard_name.h>`
|
|
||||||
|
|
||||||
This file is used to define the matrix for your keyboard. You should define at least one C macro which translates an array into a matrix representing the physical switch matrix for your keyboard. If it's possible to build your keyboard with multiple layouts you should define additional macros.
|
|
||||||
|
|
||||||
If you have only a single layout you should call this macro `LAYOUT`.
|
|
||||||
|
|
||||||
When defining multiple layouts you should have a base layout, named `LAYOUT_all`, that supports all possible switch positions on your matrix, even if that layout is impossible to build physically. This is the macro you should use in your `default` keymap. You should then have additional keymaps named `default_<layout>` that use your other layout macros. This will make it easier for people to use the layouts you define.
|
|
||||||
|
|
||||||
Layout macro names are entirely lowercase, except for the word `LAYOUT` at the front.
|
|
||||||
|
|
||||||
As an example, if you have a 60% PCB that supports ANSI and ISO you might define the following layouts and keymaps:
|
|
||||||
|
|
||||||
| Layout Name | Keymap Name | Description |
|
|
||||||
|-------------|-------------|-------------|
|
|
||||||
| LAYOUT_all | default | A layout that supports both ISO and ANSI |
|
|
||||||
| LAYOUT_ansi | default_ansi | An ANSI layout |
|
|
||||||
| LAYOUT_iso | default_iso | An ISO layout |
|
|
||||||
|
|
||||||
## Image/Hardware Files
|
|
||||||
|
|
||||||
In an effort to keep the repo size down we're no longer accepting binary files of any format, with few exceptions. Hosting them elsewhere (such as <https://imgur.com>) and linking them in the `readme.md` is preferred.
|
|
||||||
|
|
||||||
Hardware files (such as plates, cases, pcb) can be contributed to the [qmk.fm repo](https://github.com/qmk/qmk.fm) and they will be made available on [qmk.fm](http://qmk.fm). Downloadable files are stored in `/<keyboard>/` (name follows the same format as above) which are served at `http://qmk.fm/<keyboard>/`, and pages are generated from `/_pages/<keyboard>/` which are served at the same location (.md files are generated into .html files through Jekyll). Check out the `lets_split` folder for an example.
|
|
||||||
|
|
||||||
## Keyboard Defaults
|
|
||||||
|
|
||||||
Given the amount of functionality that QMK exposes it's very easy to confuse new users. When putting together the default firmware for your keyboard we recommend limiting your enabled features and options to the minimal set needed to support your hardware. Recommendations for specific features follow.
|
|
||||||
|
|
||||||
### Bootmagic and Command
|
|
||||||
|
|
||||||
[Bootmagic](feature_bootmagic.md) and [Command](feature_command.md) are two related features that allow a user to control their keyboard in non-obvious ways. We recommend you think long and hard about if you're going to enable either feature, and how you will expose this functionality. Keep in mind that users who want this functionality can enable it in their personal keymaps without affecting all the novice users who may be using your keyboard as their first programmable board.
|
|
||||||
|
|
||||||
By far the most common problem new users encounter is accidentally triggering Bootmagic while they're plugging in their keyboard. They're holding the keyboard by the bottom, unknowingly pressing in alt and spacebar, and then they find that these keys have been swapped on them. We recommend leaving this feature disabled by default, but if you do turn it on consider setting `BOOTMAGIC_KEY_SALT` to a key that is hard to press while plugging your keyboard in.
|
|
||||||
|
|
||||||
If your keyboard does not have 2 shift keys you should provide a working default for `IS_COMMAND`, even when you have set `COMMAND_ENABLE = no`. This will give your users a default to conform to if they do enable Command.
|
|
||||||
|
|
||||||
## Custom Keyboard Programming
|
|
||||||
|
|
||||||
As documented on [Customizing Functionality](custom_quantum_functions.md) you can define custom functions for your keyboard. Please keep in mind that your users may want to customize that behavior as well, and make it possible for them to do that. If you are providing a custom function, for example `process_record_kb()`, make sure that your function calls the `_user()` version of the call too. You should also take into account the return value of the `_user()` version, and only run your custom code if the user returns `true`.
|
|
||||||
|
|
||||||
## Non-Production/Handwired Projects
|
|
||||||
|
|
||||||
We're happy to accept any project that uses QMK, including prototypes and handwired ones, but we have a separate `/keyboards/handwired/` folder for them, so the main `/keyboards/` folder doesn't get overcrowded. If a prototype project becomes a production project at some point in the future, we'd be happy to move it to the main `/keyboards/` folder!
|
|
||||||
|
|
||||||
## Warnings as Errors
|
|
||||||
|
|
||||||
When developing your keyboard, keep in mind that all warnings will be treated as errors - these small warnings can build-up and cause larger errors down the road (and keeping them is generally a bad practice).
|
|
||||||
|
|
||||||
## Copyright Blurb
|
|
||||||
|
|
||||||
If you're adapting your keyboard's setup from another project, but not using the same code, but sure to update the copyright header at the top of the files to show your name, in this format:
|
|
||||||
|
|
||||||
Copyright 2017 Your Name <your@email.com>
|
|
||||||
|
|
||||||
If you are modifying someone else's code and have made only trivial changes you should leave their name in the copyright statement. If you have done significant work on the file you should add your name to theirs, like so:
|
|
||||||
|
|
||||||
Copyright 2017 Their Name <original_author@example.com> Your Name <you@example.com>
|
|
||||||
|
|
||||||
The year should be the first year the file is created. If work was done to that file in later years you can reflect that by appending the second year to the first, like so:
|
|
||||||
|
|
||||||
Copyright 2015-2017 Your Name <you@example.com>
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The core of QMK is licensed under the [GNU General Public License](https://www.gnu.org/licenses/licenses.en.html). If you are shipping binaries for AVR processors you may choose either [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) or [GPLv3](https://www.gnu.org/licenses/gpl.html). If you are shipping binaries for ARM processors you must choose [GPL Version 3](https://www.gnu.org/licenses/gpl.html) to comply with the [ChibiOS](http://www.chibios.org) GPLv3 license.
|
|
||||||
|
|
||||||
If your keyboard makes use of the [uGFX](https://ugfx.io) features within QMK you must comply with the [uGFX License](https://ugfx.io/license.html), which requires a separate commercial license before selling a device containing uGFX.
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
If you're looking for more information on making your keyboard work with QMK, [check out the hardware section](hardware.md)!
|
|
@ -1,72 +0,0 @@
|
|||||||
# How Keys Are Registered, and Interpreted by Computers
|
|
||||||
|
|
||||||
In this file, you can will learn the concepts of how keyboards work over USB,
|
|
||||||
and you'll be able to better understand what you can expect from changing your
|
|
||||||
firmware directly.
|
|
||||||
|
|
||||||
## Schematic View
|
|
||||||
|
|
||||||
Whenever you type on 1 particular key, here is the chain of actions taking
|
|
||||||
place:
|
|
||||||
|
|
||||||
``` text
|
|
||||||
+------+ +-----+ +----------+ +----------+ +----+
|
|
||||||
| User |-------->| Key |------>| Firmware |----->| USB wire |---->| OS |
|
|
||||||
+------+ +-----+ +----------+ +----------+ +----+
|
|
||||||
```
|
|
||||||
|
|
||||||
This scheme is a very simple view of what's going on, and more details follow
|
|
||||||
in the next sections.
|
|
||||||
|
|
||||||
## 1. You Press a Key
|
|
||||||
|
|
||||||
Whenever you press a key, the firmware of your keyboard can register this event.
|
|
||||||
It can register when the key is pressed, held and released.
|
|
||||||
|
|
||||||
This usually happens with a periodic scan of key presses. This speed often is limited by the mechanical key response time, the protocol to transfer those key presses (here USB HID), and by the software it is used in.
|
|
||||||
|
|
||||||
## 2. What the Firmware Sends
|
|
||||||
|
|
||||||
The [HID specification](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf) tells what a keyboard can actually send through USB to have a chance to be properly recognised. This includes a pre-defined list of scancodes which are simple numbers from `0x00` to `0xE7`. The firmware assigns a scancode to each key of the keyboard.
|
|
||||||
|
|
||||||
The firmware does not send actual letters or characters, but only scancodes.
|
|
||||||
Thus, by modifying the firmware, you can only modify what scancode is sent over
|
|
||||||
USB for a given key.
|
|
||||||
|
|
||||||
## 3. What the Operating System Does
|
|
||||||
|
|
||||||
Once the keycode reaches the operating system, a piece of software has to have
|
|
||||||
it match an actual character thanks to a keyboard layout. For example, if your
|
|
||||||
layout is set to QWERTY, a sample of the matching table is as follows:
|
|
||||||
|
|
||||||
| keycode | character |
|
|
||||||
|---------|-----------|
|
|
||||||
| 0x04 | a/A |
|
|
||||||
| 0x05 | b/B |
|
|
||||||
| 0x06 | c/C |
|
|
||||||
| ... | ... |
|
|
||||||
| 0x1C | y/Y |
|
|
||||||
| 0x1D | z/Z |
|
|
||||||
| ... | ... |
|
|
||||||
|
|
||||||
## Back to the Firmware
|
|
||||||
|
|
||||||
As the layout is generally fixed (unless you create your own), the firmware can actually call a keycode by its layout name directly to ease things for you. This is exactly what is done here with `KC_A` actually representing `0x04` in QWERTY. The full list can be found in [keycodes](keycodes.md).
|
|
||||||
|
|
||||||
## List of Characters You Can Send
|
|
||||||
|
|
||||||
Putting aside shortcuts, having a limited set of keycodes mapped to a limited layout means that **the list of characters you can assign to a given key are only the ones present in the layout**.
|
|
||||||
|
|
||||||
For example, this means that if you have a QWERTY US layout, and you want to assign one key to produce `€` (euro currency symbol), you are unable to do so, because the QWERTY US layout does not have such mapping. You could fix that by using a QWERTY UK layout, or a QWERTY US International.
|
|
||||||
|
|
||||||
You may wonder why a keyboard layout containing all of Unicode is not devised then? The limited number of keycodes available through USB simply disallows such a thing.
|
|
||||||
|
|
||||||
## How to (Maybe) Enter Unicode Characters
|
|
||||||
|
|
||||||
You can have the firmware send *sequences of keys* to use the [software Unicode Input Method](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input) of the target operating system, thus effectively entering characters independently of the layout defined in the OS.
|
|
||||||
|
|
||||||
Yet, it does come with multiple disadvantages:
|
|
||||||
|
|
||||||
- Tied to a specific OS a a time (need recompilation when changing OS);
|
|
||||||
- Within a given OS, does not work in all software;
|
|
||||||
- Limited to a subset of Unicode on some systems.
|
|
@ -1,86 +0,0 @@
|
|||||||
# I2C Master Driver
|
|
||||||
|
|
||||||
The I2C Master drivers used in QMK have a set of common functions to allow portability between MCUs.
|
|
||||||
|
|
||||||
## 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);` |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. |
|
|
||||||
|
|
||||||
### 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. |
|
|
||||||
|
|
||||||
|
|
||||||
## AVR
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
The following defines can be used to configure the I2C master driver.
|
|
||||||
|
|
||||||
|Variable |Description |Default|
|
|
||||||
|------------------|---------------------------------------------------|-------|
|
|
||||||
|`F_SCL` |Clock frequency in Hz |400KHz |
|
|
||||||
|`Prescaler` |Divides master clock to aid in I2C clock selection |1 |
|
|
||||||
|
|
||||||
AVRs usually have set GPIO which turn into I2C pins, therefore no further configuration is required.
|
|
||||||
|
|
||||||
## ARM
|
|
||||||
|
|
||||||
For ARM the Chibios I2C HAL driver is under the hood.
|
|
||||||
This section assumes an STM32 MCU.
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
Firstly the `mcuconf.h` file must be setup to enable the necessary hardware drivers.
|
|
||||||
|
|
||||||
|Variable |Description |Default|
|
|
||||||
|------------------------------|------------------------------------------------------------------------------------|-------|
|
|
||||||
|`#STM32_I2C_USE_XXX` |Enable/Disable the hardware driver XXX (each driver should be explicitly listed) |FALSE |
|
|
||||||
|`#STM32_I2C_BUSY_TIMEOUT` |Time in ms until the I2C command is aborted if no response is received |50 |
|
|
||||||
|`#STM32_I2C_XXX_IRQ_PRIORITY` |Interrupt priority for hardware driver XXX (THIS IS AN EXPERT SETTING) |10 |
|
|
||||||
|`#STM32_I2C_USE_DMA` |Enable/Disable the ability of the MCU to offload the data transfer to the DMA unit |TRUE |
|
|
||||||
|`#STM32_I2C_XXX_DMA_PRIORITY` |Priority of DMA unit for hardware driver XXX (THIS IS AN EXPERT SETTING) |1 |
|
|
||||||
|
|
||||||
Secondly, in the `halconf.h` file, `#define HAL_USE_I2C` must be set to `TRUE`. This allows ChibiOS to load its I2C driver.
|
|
||||||
|
|
||||||
Lastly, we need to assign the correct GPIO pins depending on the I2C hardware driver we want to use.
|
|
||||||
|
|
||||||
By default the I2C1 hardware driver is assumed to be used. If another hardware driver is used, `#define I2C_DRIVER I2CDX` should be added to the `config.h` file with X being the number of hardware driver used. For example is I2C3 is enabled, the `config.h` file should contain `#define I2C_DRIVER I2CD3`. This aligns the QMK I2C driver with the Chibios I2C driver.
|
|
||||||
|
|
||||||
STM32 MCUs allows a variety of pins to be configured as I2C pins depending on the hardware driver used. By default B6 and B7 are set to I2C. You can use these defines to set your i2c pins:
|
|
||||||
|
|
||||||
| Variable | Description | Default |
|
|
||||||
|-------------|----------------------------------------------|---------|
|
|
||||||
| `I2C1_BANK` | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`) | `GPIOB` |
|
|
||||||
| `I2C1_SCL` | The pin number for the SCL pin (0-9) | `6` |
|
|
||||||
| `I2C1_SDA` | The pin number for the SDA pin (0-9) | `7` |
|
|
||||||
|
|
||||||
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
|
|
||||||
void i2c_init(void)
|
|
||||||
{
|
|
||||||
setPinInput(B6); // Try releasing special pins for a short time
|
|
||||||
setPinInput(B7);
|
|
||||||
wait_ms(10); // Wait for the release to happen
|
|
||||||
|
|
||||||
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function
|
|
||||||
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B7 to I2C function
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,47 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>QMK Firmware</title>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|
||||||
<meta name="description" content="Description">
|
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css" title="light">
|
|
||||||
<link rel="stylesheet" href="qmk.css" title="dark" disabled>
|
|
||||||
<link rel="stylesheet" href="sidebar.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script>
|
|
||||||
window.$docsify = {
|
|
||||||
name: 'QMK Firmware',
|
|
||||||
nameLink: 'https://qmk.fm/',
|
|
||||||
repo: 'qmk/qmk_firmware',
|
|
||||||
loadSidebar: '_summary.md',
|
|
||||||
auto2top: true,
|
|
||||||
formatUpdated: '{YYYY}/{MM}/{DD} {HH}:{mm}',
|
|
||||||
search: {
|
|
||||||
paths: 'auto',
|
|
||||||
placeholder: 'Search Documentation...',
|
|
||||||
noData: 'We could not find any documents matching your search.',
|
|
||||||
depth: 6
|
|
||||||
},
|
|
||||||
fallbackLanguages: ['zh']
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
|
|
||||||
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
|
|
||||||
<script src="//unpkg.com/docsify/lib/plugins/emoji.min.js"></script>
|
|
||||||
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
|
|
||||||
<script src="//unpkg.com/prismjs/components/prism-c.min.js"></script>
|
|
||||||
<script src="//unpkg.com/prismjs/components/prism-cpp.min.js"></script>
|
|
||||||
<script src="//unpkg.com/prismjs/components/prism-json.min.js"></script>
|
|
||||||
<script src="//unpkg.com/prismjs/components/prism-makefile.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// Register the offline cache worker
|
|
||||||
if (typeof navigator.serviceWorker !== 'undefined') {
|
|
||||||
navigator.serviceWorker.register('sw.js')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,78 +0,0 @@
|
|||||||
# group `defines` {#group__defines}
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`define `[`SYSEX_BEGIN`](#group__defines_1ga1a3c39bb790dda8a368c4247caabcf79) |
|
|
||||||
`define `[`SYSEX_END`](#group__defines_1ga753706d1d28e6f96d7caf1973e80feed) |
|
|
||||||
`define `[`MIDI_STATUSMASK`](#group__defines_1gab78a1c818a5f5dab7a8946543f126c69) |
|
|
||||||
`define `[`MIDI_CHANMASK`](#group__defines_1ga239edc0a6f8405d3a8f2804f1590b909) |
|
|
||||||
`define `[`MIDI_CC`](#group__defines_1ga45f116a1daab76b3c930c2cecfaef215) |
|
|
||||||
`define `[`MIDI_NOTEON`](#group__defines_1gafd416f27bf3590868c0c1f55c30be4c7) |
|
|
||||||
`define `[`MIDI_NOTEOFF`](#group__defines_1gabed24bea2d989fd655e2ef2ad0765adc) |
|
|
||||||
`define `[`MIDI_AFTERTOUCH`](#group__defines_1ga3a322d8cfd53576a2e167c1840551b0f) |
|
|
||||||
`define `[`MIDI_PITCHBEND`](#group__defines_1gabcc799504e8064679bca03f232223af4) |
|
|
||||||
`define `[`MIDI_PROGCHANGE`](#group__defines_1gaefb3f1595ffbb9db66b46c2c919a3d42) |
|
|
||||||
`define `[`MIDI_CHANPRESSURE`](#group__defines_1gaeb3281cc7fcd0daade8ed3d2dfc33dbe) |
|
|
||||||
`define `[`MIDI_CLOCK`](#group__defines_1gafa5e4e295aafd15ab7893344599b3b89) |
|
|
||||||
`define `[`MIDI_TICK`](#group__defines_1ga3b99408ff864613765d4c3c2ceb52aa7) |
|
|
||||||
`define `[`MIDI_START`](#group__defines_1ga8233631c85823aa546f932ad8975caa4) |
|
|
||||||
`define `[`MIDI_CONTINUE`](#group__defines_1gab24430f0081e27215b0da84dd0ee745c) |
|
|
||||||
`define `[`MIDI_STOP`](#group__defines_1ga3af9271d4b1f0d22904a0b055f48cf62) |
|
|
||||||
`define `[`MIDI_ACTIVESENSE`](#group__defines_1gacd88ed42dba52bb4b2052c5656362677) |
|
|
||||||
`define `[`MIDI_RESET`](#group__defines_1ga02947f30ca62dc332fdeb10c5868323b) |
|
|
||||||
`define `[`MIDI_TC_QUARTERFRAME`](#group__defines_1gaaa072f33590e236d1bfd8f28e833ae31) |
|
|
||||||
`define `[`MIDI_SONGPOSITION`](#group__defines_1ga412f6ed33a2150051374bee334ee1705) |
|
|
||||||
`define `[`MIDI_SONGSELECT`](#group__defines_1gafcab254838b028365ae0259729e72c4e) |
|
|
||||||
`define `[`MIDI_TUNEREQUEST`](#group__defines_1ga8100b907b8c0a84e58b1c53dcd9bd795) |
|
|
||||||
`define `[`SYSEX_EDUMANUFID`](#group__defines_1ga5ef855ed955b00a2239ca16afbeb164f) |
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `define `[`SYSEX_BEGIN`](#group__defines_1ga1a3c39bb790dda8a368c4247caabcf79) {#group__defines_1ga1a3c39bb790dda8a368c4247caabcf79}
|
|
||||||
|
|
||||||
#### `define `[`SYSEX_END`](#group__defines_1ga753706d1d28e6f96d7caf1973e80feed) {#group__defines_1ga753706d1d28e6f96d7caf1973e80feed}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_STATUSMASK`](#group__defines_1gab78a1c818a5f5dab7a8946543f126c69) {#group__defines_1gab78a1c818a5f5dab7a8946543f126c69}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_CHANMASK`](#group__defines_1ga239edc0a6f8405d3a8f2804f1590b909) {#group__defines_1ga239edc0a6f8405d3a8f2804f1590b909}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_CC`](#group__defines_1ga45f116a1daab76b3c930c2cecfaef215) {#group__defines_1ga45f116a1daab76b3c930c2cecfaef215}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_NOTEON`](#group__defines_1gafd416f27bf3590868c0c1f55c30be4c7) {#group__defines_1gafd416f27bf3590868c0c1f55c30be4c7}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_NOTEOFF`](#group__defines_1gabed24bea2d989fd655e2ef2ad0765adc) {#group__defines_1gabed24bea2d989fd655e2ef2ad0765adc}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_AFTERTOUCH`](#group__defines_1ga3a322d8cfd53576a2e167c1840551b0f) {#group__defines_1ga3a322d8cfd53576a2e167c1840551b0f}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_PITCHBEND`](#group__defines_1gabcc799504e8064679bca03f232223af4) {#group__defines_1gabcc799504e8064679bca03f232223af4}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_PROGCHANGE`](#group__defines_1gaefb3f1595ffbb9db66b46c2c919a3d42) {#group__defines_1gaefb3f1595ffbb9db66b46c2c919a3d42}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_CHANPRESSURE`](#group__defines_1gaeb3281cc7fcd0daade8ed3d2dfc33dbe) {#group__defines_1gaeb3281cc7fcd0daade8ed3d2dfc33dbe}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_CLOCK`](#group__defines_1gafa5e4e295aafd15ab7893344599b3b89) {#group__defines_1gafa5e4e295aafd15ab7893344599b3b89}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_TICK`](#group__defines_1ga3b99408ff864613765d4c3c2ceb52aa7) {#group__defines_1ga3b99408ff864613765d4c3c2ceb52aa7}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_START`](#group__defines_1ga8233631c85823aa546f932ad8975caa4) {#group__defines_1ga8233631c85823aa546f932ad8975caa4}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_CONTINUE`](#group__defines_1gab24430f0081e27215b0da84dd0ee745c) {#group__defines_1gab24430f0081e27215b0da84dd0ee745c}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_STOP`](#group__defines_1ga3af9271d4b1f0d22904a0b055f48cf62) {#group__defines_1ga3af9271d4b1f0d22904a0b055f48cf62}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_ACTIVESENSE`](#group__defines_1gacd88ed42dba52bb4b2052c5656362677) {#group__defines_1gacd88ed42dba52bb4b2052c5656362677}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_RESET`](#group__defines_1ga02947f30ca62dc332fdeb10c5868323b) {#group__defines_1ga02947f30ca62dc332fdeb10c5868323b}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_TC_QUARTERFRAME`](#group__defines_1gaaa072f33590e236d1bfd8f28e833ae31) {#group__defines_1gaaa072f33590e236d1bfd8f28e833ae31}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_SONGPOSITION`](#group__defines_1ga412f6ed33a2150051374bee334ee1705) {#group__defines_1ga412f6ed33a2150051374bee334ee1705}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_SONGSELECT`](#group__defines_1gafcab254838b028365ae0259729e72c4e) {#group__defines_1gafcab254838b028365ae0259729e72c4e}
|
|
||||||
|
|
||||||
#### `define `[`MIDI_TUNEREQUEST`](#group__defines_1ga8100b907b8c0a84e58b1c53dcd9bd795) {#group__defines_1ga8100b907b8c0a84e58b1c53dcd9bd795}
|
|
||||||
|
|
||||||
#### `define `[`SYSEX_EDUMANUFID`](#group__defines_1ga5ef855ed955b00a2239ca16afbeb164f) {#group__defines_1ga5ef855ed955b00a2239ca16afbeb164f}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
# GPIO Control
|
|
||||||
|
|
||||||
QMK has a GPIO control abstraction layer which is microcontroller agnostic. This is done to allow easy access to pin control across different platforms.
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
The following functions can provide basic control of GPIOs and are found in `quantum/quantum.h`.
|
|
||||||
|
|
||||||
|Function |Description |
|
|
||||||
|----------------------|------------------------------------------------------------------|
|
|
||||||
|`setPinInput(pin)` |Set pin as input with high impedance (High-Z) |
|
|
||||||
|`setPinInputHigh(pin)`|Set pin as input with build in pull-up |
|
|
||||||
|`setPinInputLow(pin)` |Set pin as input with build in pull-down (Supported only on STM32)|
|
|
||||||
|`setPinOutput(pin)` |Set pin as output |
|
|
||||||
|`writePinHigh(pin)` |Set pin level as high, assuming it is an output |
|
|
||||||
|`writePinLow(pin)` |Set pin level as low, assuming it is an output |
|
|
||||||
|`writePin(pin, level)`|Set pin level, assuming it is an output |
|
|
||||||
|`readPin(pin)` |Returns the level of the pin |
|
|
||||||
|
|
||||||
## Advanced Settings
|
|
||||||
|
|
||||||
Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device and include any needed libraries. For AVR, the standard avr/io.h library is used; for STM32, the ChibiOS [PAL library](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used.
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
|||||||
# group `input_callback_reg` {#group__input__callback__reg}
|
|
||||||
|
|
||||||
These are the functions you use to register your input callbacks.
|
|
||||||
|
|
||||||
The functions are called when the appropriate midi message is matched on the associated device's input.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`public void `[`midi_register_cc_callback`](#group__input__callback__reg_1ga64ab672abbbe393c9c4a83110c8df718)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register a control change message (cc) callback.
|
|
||||||
`public void `[`midi_register_noteon_callback`](#group__input__callback__reg_1ga3962f276c17618923f1152779552103e)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register a note on callback.
|
|
||||||
`public void `[`midi_register_noteoff_callback`](#group__input__callback__reg_1gac847b66051bd6d53b762958be0ec4c6d)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register a note off callback.
|
|
||||||
`public void `[`midi_register_aftertouch_callback`](#group__input__callback__reg_1gaa95bc901bd9edff956a667c9a69dd01f)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register an after touch callback.
|
|
||||||
`public void `[`midi_register_pitchbend_callback`](#group__input__callback__reg_1ga071a28f02ba14f53de219be70ebd9a48)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register a pitch bend callback.
|
|
||||||
`public void `[`midi_register_songposition_callback`](#group__input__callback__reg_1gaf2adfd79637f3553d8f26deb1ca22ed6)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` | Register a song position callback.
|
|
||||||
`public void `[`midi_register_progchange_callback`](#group__input__callback__reg_1gae6ba1a35a4cde9bd15dd42f87401d127)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` | Register a program change callback.
|
|
||||||
`public void `[`midi_register_chanpressure_callback`](#group__input__callback__reg_1ga39b31f1f4fb93917ce039b958f21b4f5)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` | Register a channel pressure callback.
|
|
||||||
`public void `[`midi_register_songselect_callback`](#group__input__callback__reg_1gaf9aafc76a2dc4b9fdbb4106cbda6ce72)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` | Register a song select callback.
|
|
||||||
`public void `[`midi_register_tc_quarterframe_callback`](#group__input__callback__reg_1ga0a119fada2becc628cb15d753b257e6e)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` | Register a tc quarter frame callback.
|
|
||||||
`public void `[`midi_register_realtime_callback`](#group__input__callback__reg_1ga764f440e857b89084b1a07f9da2ff93a)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_one_byte_func_t func)` | Register a realtime callback.
|
|
||||||
`public void `[`midi_register_tunerequest_callback`](#group__input__callback__reg_1gae40ff3ce20bda79fef87da24b8321cb1)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_one_byte_func_t func)` | Register a tune request callback.
|
|
||||||
`public void `[`midi_register_sysex_callback`](#group__input__callback__reg_1ga63ce9631b025785c1848d0122d4c4c48)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_sysex_func_t func)` | Register a sysex callback.
|
|
||||||
`public void `[`midi_register_fallthrough_callback`](#group__input__callback__reg_1ga7ed189164aa9682862b3181153afbd94)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t func)` | Register fall through callback.
|
|
||||||
`public void `[`midi_register_catchall_callback`](#group__input__callback__reg_1ga9dbfed568d047a6cd05708f11fe39e99)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t func)` | Register a catch all callback.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_cc_callback`](#group__input__callback__reg_1ga64ab672abbbe393c9c4a83110c8df718)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1ga64ab672abbbe393c9c4a83110c8df718}
|
|
||||||
|
|
||||||
Register a control change message (cc) callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_noteon_callback`](#group__input__callback__reg_1ga3962f276c17618923f1152779552103e)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1ga3962f276c17618923f1152779552103e}
|
|
||||||
|
|
||||||
Register a note on callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_noteoff_callback`](#group__input__callback__reg_1gac847b66051bd6d53b762958be0ec4c6d)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1gac847b66051bd6d53b762958be0ec4c6d}
|
|
||||||
|
|
||||||
Register a note off callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_aftertouch_callback`](#group__input__callback__reg_1gaa95bc901bd9edff956a667c9a69dd01f)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1gaa95bc901bd9edff956a667c9a69dd01f}
|
|
||||||
|
|
||||||
Register an after touch callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_pitchbend_callback`](#group__input__callback__reg_1ga071a28f02ba14f53de219be70ebd9a48)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1ga071a28f02ba14f53de219be70ebd9a48}
|
|
||||||
|
|
||||||
Register a pitch bend callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_songposition_callback`](#group__input__callback__reg_1gaf2adfd79637f3553d8f26deb1ca22ed6)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_three_byte_func_t func)` {#group__input__callback__reg_1gaf2adfd79637f3553d8f26deb1ca22ed6}
|
|
||||||
|
|
||||||
Register a song position callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_progchange_callback`](#group__input__callback__reg_1gae6ba1a35a4cde9bd15dd42f87401d127)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` {#group__input__callback__reg_1gae6ba1a35a4cde9bd15dd42f87401d127}
|
|
||||||
|
|
||||||
Register a program change callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_chanpressure_callback`](#group__input__callback__reg_1ga39b31f1f4fb93917ce039b958f21b4f5)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` {#group__input__callback__reg_1ga39b31f1f4fb93917ce039b958f21b4f5}
|
|
||||||
|
|
||||||
Register a channel pressure callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_songselect_callback`](#group__input__callback__reg_1gaf9aafc76a2dc4b9fdbb4106cbda6ce72)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` {#group__input__callback__reg_1gaf9aafc76a2dc4b9fdbb4106cbda6ce72}
|
|
||||||
|
|
||||||
Register a song select callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_tc_quarterframe_callback`](#group__input__callback__reg_1ga0a119fada2becc628cb15d753b257e6e)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_two_byte_func_t func)` {#group__input__callback__reg_1ga0a119fada2becc628cb15d753b257e6e}
|
|
||||||
|
|
||||||
Register a tc quarter frame callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_realtime_callback`](#group__input__callback__reg_1ga764f440e857b89084b1a07f9da2ff93a)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_one_byte_func_t func)` {#group__input__callback__reg_1ga764f440e857b89084b1a07f9da2ff93a}
|
|
||||||
|
|
||||||
Register a realtime callback.
|
|
||||||
|
|
||||||
The callback will be called for all of the real time message types.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_tunerequest_callback`](#group__input__callback__reg_1gae40ff3ce20bda79fef87da24b8321cb1)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_one_byte_func_t func)` {#group__input__callback__reg_1gae40ff3ce20bda79fef87da24b8321cb1}
|
|
||||||
|
|
||||||
Register a tune request callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_sysex_callback`](#group__input__callback__reg_1ga63ce9631b025785c1848d0122d4c4c48)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_sysex_func_t func)` {#group__input__callback__reg_1ga63ce9631b025785c1848d0122d4c4c48}
|
|
||||||
|
|
||||||
Register a sysex callback.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_fallthrough_callback`](#group__input__callback__reg_1ga7ed189164aa9682862b3181153afbd94)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t func)` {#group__input__callback__reg_1ga7ed189164aa9682862b3181153afbd94}
|
|
||||||
|
|
||||||
Register fall through callback.
|
|
||||||
|
|
||||||
This is only called if a more specific callback is not matched and called. For instance, if you don't register a note on callback but you get a note on message the fall through callback will be called, if it is registered.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
||||||
#### `public void `[`midi_register_catchall_callback`](#group__input__callback__reg_1ga9dbfed568d047a6cd05708f11fe39e99)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t func)` {#group__input__callback__reg_1ga9dbfed568d047a6cd05708f11fe39e99}
|
|
||||||
|
|
||||||
Register a catch all callback.
|
|
||||||
|
|
||||||
If registered, the catch all callback is called for every message that is matched, even if a more specific or the fallthrough callback is registered.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device associate with
|
|
||||||
|
|
||||||
* `func` the callback function to register
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
|||||||
# group `midi_device` {#group__midi__device}
|
|
||||||
|
|
||||||
You use the functions when you are implementing your own midi device.
|
|
||||||
|
|
||||||
You set a send function to actually send bytes via your device, this method is called when you call a send function with this device, for instance midi_send_cc
|
|
||||||
|
|
||||||
You use the midi_device_input to process input data from the device and pass it through the device's associated callbacks.
|
|
||||||
|
|
||||||
You use the midi_device_set_pre_input_process_func if you want to have a function called at the beginning of the device's process function, generally to poll for input and pass that into midi_device_input
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`define `[`MIDI_INPUT_QUEUE_LENGTH`](#group__midi__device_1ga4aaa419caebdca2bbdfc1331e79781a8) |
|
|
||||||
`enum `[`input_state_t`](#group__midi__device_1gac203e877d3df4275ceb8e7180a61f621) |
|
|
||||||
`public void `[`midi_device_input`](#group__midi__device_1gad8d3db8eb35d9cfa51ef036a0a9d70db)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t cnt,uint8_t * input)` | Process input bytes. This function parses bytes and calls the appropriate callbacks associated with the given device. You use this function if you are creating a custom device and you want to have midi input.
|
|
||||||
`public void `[`midi_device_set_send_func`](#group__midi__device_1ga59f5a46bdd4452f186cc73d9e96d4673)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t send_func)` | Set the callback function that will be used for sending output data bytes. This is only used if you're creating a custom device. You'll most likely want the callback function to disable interrupts so that you can call the various midi send functions without worrying about locking.
|
|
||||||
`public void `[`midi_device_set_pre_input_process_func`](#group__midi__device_1ga4de0841b87c04fc23cb56b6451f33b69)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_no_byte_func_t pre_process_func)` | Set a callback which is called at the beginning of the midi_device_process call. This can be used to poll for input data and send the data through the midi_device_input function. You'll probably only use this if you're creating a custom device.
|
|
||||||
`struct `[`_midi_device`](docs/api_midi_device.md#struct__midi__device) | This structure represents the input and output functions and processing data for a midi device.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `define `[`MIDI_INPUT_QUEUE_LENGTH`](#group__midi__device_1ga4aaa419caebdca2bbdfc1331e79781a8) {#group__midi__device_1ga4aaa419caebdca2bbdfc1331e79781a8}
|
|
||||||
|
|
||||||
#### `enum `[`input_state_t`](#group__midi__device_1gac203e877d3df4275ceb8e7180a61f621) {#group__midi__device_1gac203e877d3df4275ceb8e7180a61f621}
|
|
||||||
|
|
||||||
Values | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
IDLE |
|
|
||||||
ONE_BYTE_MESSAGE |
|
|
||||||
TWO_BYTE_MESSAGE |
|
|
||||||
THREE_BYTE_MESSAGE |
|
|
||||||
SYSEX_MESSAGE |
|
|
||||||
|
|
||||||
#### `public void `[`midi_device_input`](#group__midi__device_1gad8d3db8eb35d9cfa51ef036a0a9d70db)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t cnt,uint8_t * input)` {#group__midi__device_1gad8d3db8eb35d9cfa51ef036a0a9d70db}
|
|
||||||
|
|
||||||
Process input bytes. This function parses bytes and calls the appropriate callbacks associated with the given device. You use this function if you are creating a custom device and you want to have midi input.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the midi device to associate the input with
|
|
||||||
|
|
||||||
* `cnt` the number of bytes you are processing
|
|
||||||
|
|
||||||
* `input` the bytes to process
|
|
||||||
|
|
||||||
#### `public void `[`midi_device_set_send_func`](#group__midi__device_1ga59f5a46bdd4452f186cc73d9e96d4673)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_var_byte_func_t send_func)` {#group__midi__device_1ga59f5a46bdd4452f186cc73d9e96d4673}
|
|
||||||
|
|
||||||
Set the callback function that will be used for sending output data bytes. This is only used if you're creating a custom device. You'll most likely want the callback function to disable interrupts so that you can call the various midi send functions without worrying about locking.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the midi device to associate this callback with
|
|
||||||
|
|
||||||
* `send_func` the callback function that will do the sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_device_set_pre_input_process_func`](#group__midi__device_1ga4de0841b87c04fc23cb56b6451f33b69)`(`[`MidiDevice`](#struct__midi__device)` * device,midi_no_byte_func_t pre_process_func)` {#group__midi__device_1ga4de0841b87c04fc23cb56b6451f33b69}
|
|
||||||
|
|
||||||
Set a callback which is called at the beginning of the midi_device_process call. This can be used to poll for input data and send the data through the midi_device_input function. You'll probably only use this if you're creating a custom device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the midi device to associate this callback with
|
|
||||||
|
|
||||||
* `midi_no_byte_func_t` the actual callback function
|
|
||||||
|
|
||||||
# struct `_midi_device` {#struct__midi__device}
|
|
||||||
|
|
||||||
This structure represents the input and output functions and processing data for a midi device.
|
|
||||||
|
|
||||||
A device can represent an actual physical device [serial port, usb port] or something virtual. You should not need to modify this structure directly.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`public midi_var_byte_func_t `[`send_func`](docs/api_midi_device.md#struct__midi__device_1a25d4c94b4bbccd5b98f1032b469f3ff9) |
|
|
||||||
`public midi_three_byte_func_t `[`input_cc_callback`](docs/api_midi_device.md#struct__midi__device_1a6da5236c1bc73877728df92d213a78d1) |
|
|
||||||
`public midi_three_byte_func_t `[`input_noteon_callback`](docs/api_midi_device.md#struct__midi__device_1aa10b15cf1a7fb825a5df0d2abbe34a1c) |
|
|
||||||
`public midi_three_byte_func_t `[`input_noteoff_callback`](docs/api_midi_device.md#struct__midi__device_1aaf290043078534d3a5a0ea4c840eba84) |
|
|
||||||
`public midi_three_byte_func_t `[`input_aftertouch_callback`](docs/api_midi_device.md#struct__midi__device_1acb0b4901c545cec4b28b126f2d8c315f) |
|
|
||||||
`public midi_three_byte_func_t `[`input_pitchbend_callback`](docs/api_midi_device.md#struct__midi__device_1a305fea672caeb996f2233bf8cd2bef18) |
|
|
||||||
`public midi_three_byte_func_t `[`input_songposition_callback`](docs/api_midi_device.md#struct__midi__device_1a5f3f13638b3fef3fc561ed1bf301d586) |
|
|
||||||
`public midi_two_byte_func_t `[`input_progchange_callback`](docs/api_midi_device.md#struct__midi__device_1adaf1da617c9a10a9dcad00ab1959d3da) |
|
|
||||||
`public midi_two_byte_func_t `[`input_chanpressure_callback`](docs/api_midi_device.md#struct__midi__device_1ab7ca2925c539915d43974eff604d85f7) |
|
|
||||||
`public midi_two_byte_func_t `[`input_songselect_callback`](docs/api_midi_device.md#struct__midi__device_1a89bed8a5a55376120cfc0a62b42f057f) |
|
|
||||||
`public midi_two_byte_func_t `[`input_tc_quarterframe_callback`](docs/api_midi_device.md#struct__midi__device_1ad9813e75d22e284f9f65a907d20600f0) |
|
|
||||||
`public midi_one_byte_func_t `[`input_realtime_callback`](docs/api_midi_device.md#struct__midi__device_1a9448eba4afb7e43650434748db3777be) |
|
|
||||||
`public midi_one_byte_func_t `[`input_tunerequest_callback`](docs/api_midi_device.md#struct__midi__device_1a0cb8fd53e00cf1d4202d4fa04d038e8d) |
|
|
||||||
`public midi_sysex_func_t `[`input_sysex_callback`](docs/api_midi_device.md#struct__midi__device_1afff9a0ce641762aaef24c1e6953ec9a2) |
|
|
||||||
`public midi_var_byte_func_t `[`input_fallthrough_callback`](docs/api_midi_device.md#struct__midi__device_1abb974ec6d734001b4a0e370f292be503) |
|
|
||||||
`public midi_var_byte_func_t `[`input_catchall_callback`](docs/api_midi_device.md#struct__midi__device_1aae0d535129d4fd650edc98eb3f7584f8) |
|
|
||||||
`public midi_no_byte_func_t `[`pre_input_process_callback`](docs/api_midi_device.md#struct__midi__device_1aeb0bb8923d66c23d874e177dc4265754) |
|
|
||||||
`public uint8_t `[`input_buffer`](docs/api_midi_device.md#struct__midi__device_1a7c5684857d6af4ebc4dc12da27bd6b2a) |
|
|
||||||
`public input_state_t `[`input_state`](docs/api_midi_device.md#struct__midi__device_1a69a687d2d1c449ec15a11c07a5722e39) |
|
|
||||||
`public uint16_t `[`input_count`](docs/api_midi_device.md#struct__midi__device_1a68dea8e7b6151e89c85c95caa612ee5d) |
|
|
||||||
`public uint8_t `[`input_queue_data`](docs/api_midi_device.md#struct__midi__device_1ada41de021135dc423abedcbb30f366ff) |
|
|
||||||
`public `[`byteQueue_t`](#structbyte_queue__t)` `[`input_queue`](#struct__midi__device_1a49c8538a8a02193c58e28a56eb695d8f) |
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `public midi_var_byte_func_t `[`send_func`](docs/api_midi_device.md#struct__midi__device_1a25d4c94b4bbccd5b98f1032b469f3ff9) {#struct__midi__device_1a25d4c94b4bbccd5b98f1032b469f3ff9}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_cc_callback`](docs/api_midi_device.md#struct__midi__device_1a6da5236c1bc73877728df92d213a78d1) {#struct__midi__device_1a6da5236c1bc73877728df92d213a78d1}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_noteon_callback`](docs/api_midi_device.md#struct__midi__device_1aa10b15cf1a7fb825a5df0d2abbe34a1c) {#struct__midi__device_1aa10b15cf1a7fb825a5df0d2abbe34a1c}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_noteoff_callback`](docs/api_midi_device.md#struct__midi__device_1aaf290043078534d3a5a0ea4c840eba84) {#struct__midi__device_1aaf290043078534d3a5a0ea4c840eba84}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_aftertouch_callback`](docs/api_midi_device.md#struct__midi__device_1acb0b4901c545cec4b28b126f2d8c315f) {#struct__midi__device_1acb0b4901c545cec4b28b126f2d8c315f}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_pitchbend_callback`](docs/api_midi_device.md#struct__midi__device_1a305fea672caeb996f2233bf8cd2bef18) {#struct__midi__device_1a305fea672caeb996f2233bf8cd2bef18}
|
|
||||||
|
|
||||||
#### `public midi_three_byte_func_t `[`input_songposition_callback`](docs/api_midi_device.md#struct__midi__device_1a5f3f13638b3fef3fc561ed1bf301d586) {#struct__midi__device_1a5f3f13638b3fef3fc561ed1bf301d586}
|
|
||||||
|
|
||||||
#### `public midi_two_byte_func_t `[`input_progchange_callback`](docs/api_midi_device.md#struct__midi__device_1adaf1da617c9a10a9dcad00ab1959d3da) {#struct__midi__device_1adaf1da617c9a10a9dcad00ab1959d3da}
|
|
||||||
|
|
||||||
#### `public midi_two_byte_func_t `[`input_chanpressure_callback`](docs/api_midi_device.md#struct__midi__device_1ab7ca2925c539915d43974eff604d85f7) {#struct__midi__device_1ab7ca2925c539915d43974eff604d85f7}
|
|
||||||
|
|
||||||
#### `public midi_two_byte_func_t `[`input_songselect_callback`](docs/api_midi_device.md#struct__midi__device_1a89bed8a5a55376120cfc0a62b42f057f) {#struct__midi__device_1a89bed8a5a55376120cfc0a62b42f057f}
|
|
||||||
|
|
||||||
#### `public midi_two_byte_func_t `[`input_tc_quarterframe_callback`](docs/api_midi_device.md#struct__midi__device_1ad9813e75d22e284f9f65a907d20600f0) {#struct__midi__device_1ad9813e75d22e284f9f65a907d20600f0}
|
|
||||||
|
|
||||||
#### `public midi_one_byte_func_t `[`input_realtime_callback`](docs/api_midi_device.md#struct__midi__device_1a9448eba4afb7e43650434748db3777be) {#struct__midi__device_1a9448eba4afb7e43650434748db3777be}
|
|
||||||
|
|
||||||
#### `public midi_one_byte_func_t `[`input_tunerequest_callback`](docs/api_midi_device.md#struct__midi__device_1a0cb8fd53e00cf1d4202d4fa04d038e8d) {#struct__midi__device_1a0cb8fd53e00cf1d4202d4fa04d038e8d}
|
|
||||||
|
|
||||||
#### `public midi_sysex_func_t `[`input_sysex_callback`](docs/api_midi_device.md#struct__midi__device_1afff9a0ce641762aaef24c1e6953ec9a2) {#struct__midi__device_1afff9a0ce641762aaef24c1e6953ec9a2}
|
|
||||||
|
|
||||||
#### `public midi_var_byte_func_t `[`input_fallthrough_callback`](docs/api_midi_device.md#struct__midi__device_1abb974ec6d734001b4a0e370f292be503) {#struct__midi__device_1abb974ec6d734001b4a0e370f292be503}
|
|
||||||
|
|
||||||
#### `public midi_var_byte_func_t `[`input_catchall_callback`](docs/api_midi_device.md#struct__midi__device_1aae0d535129d4fd650edc98eb3f7584f8) {#struct__midi__device_1aae0d535129d4fd650edc98eb3f7584f8}
|
|
||||||
|
|
||||||
#### `public midi_no_byte_func_t `[`pre_input_process_callback`](docs/api_midi_device.md#struct__midi__device_1aeb0bb8923d66c23d874e177dc4265754) {#struct__midi__device_1aeb0bb8923d66c23d874e177dc4265754}
|
|
||||||
|
|
||||||
#### `public uint8_t `[`input_buffer`](docs/api_midi_device.md#struct__midi__device_1a7c5684857d6af4ebc4dc12da27bd6b2a) {#struct__midi__device_1a7c5684857d6af4ebc4dc12da27bd6b2a}
|
|
||||||
|
|
||||||
#### `public input_state_t `[`input_state`](docs/api_midi_device.md#struct__midi__device_1a69a687d2d1c449ec15a11c07a5722e39) {#struct__midi__device_1a69a687d2d1c449ec15a11c07a5722e39}
|
|
||||||
|
|
||||||
#### `public uint16_t `[`input_count`](docs/api_midi_device.md#struct__midi__device_1a68dea8e7b6151e89c85c95caa612ee5d) {#struct__midi__device_1a68dea8e7b6151e89c85c95caa612ee5d}
|
|
||||||
|
|
||||||
#### `public uint8_t `[`input_queue_data`](docs/api_midi_device.md#struct__midi__device_1ada41de021135dc423abedcbb30f366ff) {#struct__midi__device_1ada41de021135dc423abedcbb30f366ff}
|
|
||||||
|
|
||||||
#### `public `[`byteQueue_t`](#structbyte_queue__t)` `[`input_queue`](#struct__midi__device_1a49c8538a8a02193c58e28a56eb695d8f) {#struct__midi__device_1a49c8538a8a02193c58e28a56eb695d8f}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
# group `midi_device_setup_process` {#group__midi__device__setup__process}
|
|
||||||
|
|
||||||
These are method that you must use to initialize and run a device.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`public void `[`midi_device_init`](#group__midi__device__setup__process_1gaf29deddc94ea98a59daa0bde1aefd9d9)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Initialize a device.
|
|
||||||
`public void `[`midi_device_process`](#group__midi__device__setup__process_1gaa3d5993d0e998a1b59bbf5ab9c7b492b)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Process input data.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `public void `[`midi_device_init`](#group__midi__device__setup__process_1gaf29deddc94ea98a59daa0bde1aefd9d9)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__midi__device__setup__process_1gaf29deddc94ea98a59daa0bde1aefd9d9}
|
|
||||||
|
|
||||||
Initialize a device.
|
|
||||||
|
|
||||||
You must call this before using the device in question.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to initialize
|
|
||||||
|
|
||||||
#### `public void `[`midi_device_process`](#group__midi__device__setup__process_1gaa3d5993d0e998a1b59bbf5ab9c7b492b)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__midi__device__setup__process_1gaa3d5993d0e998a1b59bbf5ab9c7b492b}
|
|
||||||
|
|
||||||
Process input data.
|
|
||||||
|
|
||||||
This method drives the input processing, you must call this method frequently if you expect to have your input callbacks called.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to process
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
# group `midi_util` {#group__midi__util}
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`enum `[`midi_packet_length_t`](#group__midi__util_1gae29ff56aee2b430ffe53933b97e5e79e) | An enumeration of the possible packet length values.
|
|
||||||
`public bool `[`midi_is_statusbyte`](#group__midi__util_1ga12e3b42ff9cbb4b4f2bc455fc8743ee5)`(uint8_t theByte)` | Test to see if the byte given is a status byte.
|
|
||||||
`public bool `[`midi_is_realtime`](#group__midi__util_1gad2f52c363e34a8000d80c983c324e2d7)`(uint8_t theByte)` | Test to see if the byte given is a realtime message.
|
|
||||||
`public `[`midi_packet_length_t`](#group__midi__util_1gae29ff56aee2b430ffe53933b97e5e79e)` `[`midi_packet_length`](#group__midi__util_1gaa168b43af6ae9de0debce1625e4b8175)`(uint8_t status)` | Find the length of the packet associated with the status byte given.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `enum `[`midi_packet_length_t`](#group__midi__util_1gae29ff56aee2b430ffe53933b97e5e79e) {#group__midi__util_1gae29ff56aee2b430ffe53933b97e5e79e}
|
|
||||||
|
|
||||||
Values | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
UNDEFINED |
|
|
||||||
ONE |
|
|
||||||
TWO |
|
|
||||||
THREE |
|
|
||||||
|
|
||||||
An enumeration of the possible packet length values.
|
|
||||||
|
|
||||||
#### `public bool `[`midi_is_statusbyte`](#group__midi__util_1ga12e3b42ff9cbb4b4f2bc455fc8743ee5)`(uint8_t theByte)` {#group__midi__util_1ga12e3b42ff9cbb4b4f2bc455fc8743ee5}
|
|
||||||
|
|
||||||
Test to see if the byte given is a status byte.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `theByte` the byte to test
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
true if the byte given is a midi status byte
|
|
||||||
|
|
||||||
#### `public bool `[`midi_is_realtime`](#group__midi__util_1gad2f52c363e34a8000d80c983c324e2d7)`(uint8_t theByte)` {#group__midi__util_1gad2f52c363e34a8000d80c983c324e2d7}
|
|
||||||
|
|
||||||
Test to see if the byte given is a realtime message.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `theByte` the byte to test
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
true if it is a realtime message, false otherwise
|
|
||||||
|
|
||||||
#### `public `[`midi_packet_length_t`](#group__midi__util_1gae29ff56aee2b430ffe53933b97e5e79e)` `[`midi_packet_length`](#group__midi__util_1gaa168b43af6ae9de0debce1625e4b8175)`(uint8_t status)` {#group__midi__util_1gaa168b43af6ae9de0debce1625e4b8175}
|
|
||||||
|
|
||||||
Find the length of the packet associated with the status byte given.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `status` the status byte
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
the length of the packet, will return UNDEFINED if the byte is not a status byte or if it is a sysex status byte
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
|||||||
# group `send_functions` {#group__send__functions}
|
|
||||||
|
|
||||||
These are the functions you use to send midi data through a device.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`public void `[`midi_send_cc`](#group__send__functions_1gaaf884811c92df405ca8fe1a00082f960)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t val)` | Send a control change message (cc) via the given device.
|
|
||||||
`public void `[`midi_send_noteon`](#group__send__functions_1ga467bcf46dbf03ec269ce565b46bc2775)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t vel)` | Send a note on message via the given device.
|
|
||||||
`public void `[`midi_send_noteoff`](#group__send__functions_1gaedb7d8805425eef5d47d57ddcb4c7a49)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t vel)` | Send a note off message via the given device.
|
|
||||||
`public void `[`midi_send_aftertouch`](#group__send__functions_1ga0014847571317a0e34b2ef46a6bc584f)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t note_num,uint8_t amt)` | Send an after touch message via the given device.
|
|
||||||
`public void `[`midi_send_pitchbend`](#group__send__functions_1gae5a4a1e71611e7534be80af9ce3d3491)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,int16_t amt)` | Send a pitch bend message via the given device.
|
|
||||||
`public void `[`midi_send_programchange`](#group__send__functions_1ga7b15588ef25e5e1ff09c2afc3151ce86)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num)` | Send a program change message via the given device.
|
|
||||||
`public void `[`midi_send_channelpressure`](#group__send__functions_1gaf23e69fdf812e89c0036f51f88ab2e1b)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t amt)` | Send a channel pressure message via the given device.
|
|
||||||
`public void `[`midi_send_clock`](#group__send__functions_1ga4e1b11a7cdb0875f6e03ce7c79c581aa)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a clock message via the given device.
|
|
||||||
`public void `[`midi_send_tick`](#group__send__functions_1ga2b43c7d433d940c5b907595aac947972)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a tick message via the given device.
|
|
||||||
`public void `[`midi_send_start`](#group__send__functions_1ga1569749a8d58ccc56789289d7c7245cc)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a start message via the given device.
|
|
||||||
`public void `[`midi_send_continue`](#group__send__functions_1gaed5dc29d754a27372e89ab8bc20ee120)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a continue message via the given device.
|
|
||||||
`public void `[`midi_send_stop`](#group__send__functions_1ga026e1a620276cb653ac501aa0d12a988)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a stop message via the given device.
|
|
||||||
`public void `[`midi_send_activesense`](#group__send__functions_1ga9b6e4c6ce4719d2604187b325620db37)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send an active sense message via the given device.
|
|
||||||
`public void `[`midi_send_reset`](#group__send__functions_1ga3671e39a6d93ca9568fc493001af1b1b)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a reset message via the given device.
|
|
||||||
`public void `[`midi_send_tcquarterframe`](#group__send__functions_1ga5b85639910eec280bb744c934d0fd45a)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t time)` | Send a tc quarter frame message via the given device.
|
|
||||||
`public void `[`midi_send_songposition`](#group__send__functions_1gab1c9eeef3b57a8cd2e6128d18e85eb7f)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t pos)` | Send a song position message via the given device.
|
|
||||||
`public void `[`midi_send_songselect`](#group__send__functions_1ga42de7838ba70d949af9a50f9facc3c50)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t song)` | Send a song select message via the given device.
|
|
||||||
`public void `[`midi_send_tunerequest`](#group__send__functions_1ga8db6c7e04d48e4d2266dd59118ca0656)`(`[`MidiDevice`](#struct__midi__device)` * device)` | Send a tune request message via the given device.
|
|
||||||
`public void `[`midi_send_byte`](#group__send__functions_1ga857e85eb90b288385642d4d991e09881)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t b)` | Send a byte via the given device.
|
|
||||||
`public void `[`midi_send_data`](#group__send__functions_1ga36e2f2e45369d911b76969361679054b)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t count,uint8_t byte0,uint8_t byte1,uint8_t byte2)` | Send up to 3 bytes of data.
|
|
||||||
`public void `[`midi_send_array`](#group__send__functions_1ga245243cb1da18d2cea18d4b18d846ead)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t count,uint8_t * array)` | Send an array of formatted midi data.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_cc`](#group__send__functions_1gaaf884811c92df405ca8fe1a00082f960)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t val)` {#group__send__functions_1gaaf884811c92df405ca8fe1a00082f960}
|
|
||||||
|
|
||||||
Send a control change message (cc) via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `num` the cc num
|
|
||||||
|
|
||||||
* `val` the value of that cc num
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_noteon`](#group__send__functions_1ga467bcf46dbf03ec269ce565b46bc2775)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t vel)` {#group__send__functions_1ga467bcf46dbf03ec269ce565b46bc2775}
|
|
||||||
|
|
||||||
Send a note on message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `num` the note number
|
|
||||||
|
|
||||||
* `vel` the note velocity
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_noteoff`](#group__send__functions_1gaedb7d8805425eef5d47d57ddcb4c7a49)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num,uint8_t vel)` {#group__send__functions_1gaedb7d8805425eef5d47d57ddcb4c7a49}
|
|
||||||
|
|
||||||
Send a note off message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `num` the note number
|
|
||||||
|
|
||||||
* `vel` the note velocity
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_aftertouch`](#group__send__functions_1ga0014847571317a0e34b2ef46a6bc584f)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t note_num,uint8_t amt)` {#group__send__functions_1ga0014847571317a0e34b2ef46a6bc584f}
|
|
||||||
|
|
||||||
Send an after touch message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `note_num` the note number
|
|
||||||
|
|
||||||
* `amt` the after touch amount
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_pitchbend`](#group__send__functions_1gae5a4a1e71611e7534be80af9ce3d3491)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,int16_t amt)` {#group__send__functions_1gae5a4a1e71611e7534be80af9ce3d3491}
|
|
||||||
|
|
||||||
Send a pitch bend message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `amt` the bend amount range: -8192..8191, 0 means no bend
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_programchange`](#group__send__functions_1ga7b15588ef25e5e1ff09c2afc3151ce86)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t num)` {#group__send__functions_1ga7b15588ef25e5e1ff09c2afc3151ce86}
|
|
||||||
|
|
||||||
Send a program change message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `num` the program to change to
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_channelpressure`](#group__send__functions_1gaf23e69fdf812e89c0036f51f88ab2e1b)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t chan,uint8_t amt)` {#group__send__functions_1gaf23e69fdf812e89c0036f51f88ab2e1b}
|
|
||||||
|
|
||||||
Send a channel pressure message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `chan` the channel to send on, 0-15
|
|
||||||
|
|
||||||
* `amt` the amount of channel pressure
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_clock`](#group__send__functions_1ga4e1b11a7cdb0875f6e03ce7c79c581aa)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga4e1b11a7cdb0875f6e03ce7c79c581aa}
|
|
||||||
|
|
||||||
Send a clock message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_tick`](#group__send__functions_1ga2b43c7d433d940c5b907595aac947972)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga2b43c7d433d940c5b907595aac947972}
|
|
||||||
|
|
||||||
Send a tick message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_start`](#group__send__functions_1ga1569749a8d58ccc56789289d7c7245cc)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga1569749a8d58ccc56789289d7c7245cc}
|
|
||||||
|
|
||||||
Send a start message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_continue`](#group__send__functions_1gaed5dc29d754a27372e89ab8bc20ee120)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1gaed5dc29d754a27372e89ab8bc20ee120}
|
|
||||||
|
|
||||||
Send a continue message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_stop`](#group__send__functions_1ga026e1a620276cb653ac501aa0d12a988)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga026e1a620276cb653ac501aa0d12a988}
|
|
||||||
|
|
||||||
Send a stop message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_activesense`](#group__send__functions_1ga9b6e4c6ce4719d2604187b325620db37)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga9b6e4c6ce4719d2604187b325620db37}
|
|
||||||
|
|
||||||
Send an active sense message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_reset`](#group__send__functions_1ga3671e39a6d93ca9568fc493001af1b1b)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga3671e39a6d93ca9568fc493001af1b1b}
|
|
||||||
|
|
||||||
Send a reset message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_tcquarterframe`](#group__send__functions_1ga5b85639910eec280bb744c934d0fd45a)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t time)` {#group__send__functions_1ga5b85639910eec280bb744c934d0fd45a}
|
|
||||||
|
|
||||||
Send a tc quarter frame message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `time` the time of this quarter frame, range 0..16383
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_songposition`](#group__send__functions_1gab1c9eeef3b57a8cd2e6128d18e85eb7f)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t pos)` {#group__send__functions_1gab1c9eeef3b57a8cd2e6128d18e85eb7f}
|
|
||||||
|
|
||||||
Send a song position message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `pos` the song position
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_songselect`](#group__send__functions_1ga42de7838ba70d949af9a50f9facc3c50)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t song)` {#group__send__functions_1ga42de7838ba70d949af9a50f9facc3c50}
|
|
||||||
|
|
||||||
Send a song select message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `song` the song to select
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_tunerequest`](#group__send__functions_1ga8db6c7e04d48e4d2266dd59118ca0656)`(`[`MidiDevice`](#struct__midi__device)` * device)` {#group__send__functions_1ga8db6c7e04d48e4d2266dd59118ca0656}
|
|
||||||
|
|
||||||
Send a tune request message via the given device.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_byte`](#group__send__functions_1ga857e85eb90b288385642d4d991e09881)`(`[`MidiDevice`](#struct__midi__device)` * device,uint8_t b)` {#group__send__functions_1ga857e85eb90b288385642d4d991e09881}
|
|
||||||
|
|
||||||
Send a byte via the given device.
|
|
||||||
|
|
||||||
This is a generic method for sending data via the given midi device. This would be useful for sending sysex data or messages that are not implemented in this API, if there are any. Please contact the author if you find some so we can add them.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `b` the byte to send
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_data`](#group__send__functions_1ga36e2f2e45369d911b76969361679054b)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t count,uint8_t byte0,uint8_t byte1,uint8_t byte2)` {#group__send__functions_1ga36e2f2e45369d911b76969361679054b}
|
|
||||||
|
|
||||||
Send up to 3 bytes of data.
|
|
||||||
|
|
||||||
% 4 is applied to count so that you can use this to pass sysex through
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `count` the count of bytes to send, %4 is applied
|
|
||||||
|
|
||||||
* `byte0` the first byte
|
|
||||||
|
|
||||||
* `byte1` the second byte, ignored if cnt % 4 != 2
|
|
||||||
|
|
||||||
* `byte2` the third byte, ignored if cnt % 4 != 3
|
|
||||||
|
|
||||||
#### `public void `[`midi_send_array`](#group__send__functions_1ga245243cb1da18d2cea18d4b18d846ead)`(`[`MidiDevice`](#struct__midi__device)` * device,uint16_t count,uint8_t * array)` {#group__send__functions_1ga245243cb1da18d2cea18d4b18d846ead}
|
|
||||||
|
|
||||||
Send an array of formatted midi data.
|
|
||||||
|
|
||||||
Can be used for sysex.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `device` the device to use for sending
|
|
||||||
|
|
||||||
* `count` the count of bytes to send
|
|
||||||
|
|
||||||
* `array` the array of bytes
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
|||||||
# group `sysex_tools` {#group__sysex__tools}
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Members | Descriptions
|
|
||||||
--------------------------------|---------------------------------------------
|
|
||||||
`public uint16_t `[`sysex_encoded_length`](#group__sysex__tools_1ga061e5607030412d6e62e2390d8013f0a)`(uint16_t decoded_length)` | Compute the length of a message after it is encoded.
|
|
||||||
`public uint16_t `[`sysex_decoded_length`](#group__sysex__tools_1ga121fc227d3acc1c0ea08c9a5c26fa3b0)`(uint16_t encoded_length)` | Compute the length of a message after it is decoded.
|
|
||||||
`public uint16_t `[`sysex_encode`](#group__sysex__tools_1ga54d77f8d32f92a6f329daefa2b314742)`(uint8_t * encoded,const uint8_t * source,uint16_t length)` | Encode data so that it can be transmitted safely in a sysex message.
|
|
||||||
`public uint16_t `[`sysex_decode`](#group__sysex__tools_1gaaad1d9ba2d5eca709a0ab4ba40662229)`(uint8_t * decoded,const uint8_t * source,uint16_t length)` | Decode encoded data.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
#### `public uint16_t `[`sysex_encoded_length`](#group__sysex__tools_1ga061e5607030412d6e62e2390d8013f0a)`(uint16_t decoded_length)` {#group__sysex__tools_1ga061e5607030412d6e62e2390d8013f0a}
|
|
||||||
|
|
||||||
Compute the length of a message after it is encoded.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `decoded_length` The length, in bytes, of the message to encode.
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
The length, in bytes, of the message after encodeing.
|
|
||||||
|
|
||||||
#### `public uint16_t `[`sysex_decoded_length`](#group__sysex__tools_1ga121fc227d3acc1c0ea08c9a5c26fa3b0)`(uint16_t encoded_length)` {#group__sysex__tools_1ga121fc227d3acc1c0ea08c9a5c26fa3b0}
|
|
||||||
|
|
||||||
Compute the length of a message after it is decoded.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `encoded_length` The length, in bytes, of the encoded message.
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
The length, in bytes, of the message after it is decoded.
|
|
||||||
|
|
||||||
#### `public uint16_t `[`sysex_encode`](#group__sysex__tools_1ga54d77f8d32f92a6f329daefa2b314742)`(uint8_t * encoded,const uint8_t * source,uint16_t length)` {#group__sysex__tools_1ga54d77f8d32f92a6f329daefa2b314742}
|
|
||||||
|
|
||||||
Encode data so that it can be transmitted safely in a sysex message.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `encoded` The output data buffer, must be at least sysex_encoded_length(length) bytes long.
|
|
||||||
|
|
||||||
* `source` The input buffer of data to be encoded.
|
|
||||||
|
|
||||||
* `length` The number of bytes from the input buffer to encode.
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
number of bytes encoded.
|
|
||||||
|
|
||||||
#### `public uint16_t `[`sysex_decode`](#group__sysex__tools_1gaaad1d9ba2d5eca709a0ab4ba40662229)`(uint8_t * decoded,const uint8_t * source,uint16_t length)` {#group__sysex__tools_1gaaad1d9ba2d5eca709a0ab4ba40662229}
|
|
||||||
|
|
||||||
Decode encoded data.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
* `decoded` The output data buffer, must be at least sysex_decoded_length(length) bytes long.
|
|
||||||
|
|
||||||
* `source` The input buffer of data to be decoded.
|
|
||||||
|
|
||||||
* `length` The number of bytes from the input buffer to decode.
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
number of bytes decoded.
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
|||||||
# ISP Flashing Guide
|
|
||||||
|
|
||||||
If you're having trouble flashing/erasing your board, and running into cryptic error messages like any of the following:
|
|
||||||
|
|
||||||
libusb: warning [darwin_transfer_status] transfer error: timed out
|
|
||||||
dfu.c:844: -ETIMEDOUT: Transfer timed out, NAK 0xffffffc4 (-60)
|
|
||||||
atmel.c:1627: atmel_flash: flash data dfu_download failed.
|
|
||||||
atmel.c:1629: Expected message length of 1072, got -60.
|
|
||||||
atmel.c:1434: Error flashing the block: err -2.
|
|
||||||
ERROR
|
|
||||||
Memory write error, use debug for more info.
|
|
||||||
commands.c:360: Error writing memory data. (err -4)
|
|
||||||
|
|
||||||
dfu.c:844: -EPIPE: a) Babble detect or b) Endpoint stalled 0xffffffe0 (-32)
|
|
||||||
Device is write protected.
|
|
||||||
dfu.c:252: dfu_clear_status( 0x7fff4fc2ea80 )
|
|
||||||
atmel.c:1434: Error flashing the block: err -2.
|
|
||||||
ERROR
|
|
||||||
Memory write error, use debug for more info.
|
|
||||||
commands.c:360: Error writing memory data. (err -4)
|
|
||||||
|
|
||||||
You're likely going to need to ISP flash your board/device to get it working again. Luckily, this process is pretty straight-forward, provided you have any extra programmable keyboard, Pro Micro, or Teensy 2.0/Teensy 2.0++. There are also dedicated ISP flashers available for this, but most cost >$15, and it's assumed that if you are googling this error, this is the first you've heard about ISP flashing, and don't have one readily available (whereas you might have some other AVR board). __We'll be using a Teensy 2.0 or Pro Micro with Windows 10 in this guide__ - if you are comfortable doing this on another system, please consider editing this guide and contributing those instructions!
|
|
||||||
|
|
||||||
## Software Needed
|
|
||||||
|
|
||||||
* [Teensy Loader](https://www.pjrc.com/teensy/loader.html) (if using a Teensy)
|
|
||||||
* QMK Toolbox (flash as usual - be sure to select the correct MCU) or `avrdude` via [WinAVR](http://www.ladyada.net/learn/avr/setup-win.html) (for Teensy & Pro Micro)
|
|
||||||
|
|
||||||
## Wiring
|
|
||||||
|
|
||||||
This is pretty straight-forward - we'll be connecting like-things to like-things in the following manner:
|
|
||||||
|
|
||||||
### Teensy 2.0
|
|
||||||
|
|
||||||
Teensy B0 <-> Keyboard RESET
|
|
||||||
Teensy B1 <-> Keyboard B1 (SCLK)
|
|
||||||
Teensy B2 <-> Keyboard B2 (MOSI)
|
|
||||||
Teensy B3 <-> Keyboard B3 (MISO)
|
|
||||||
Teensy VCC <-> Keyboard VCC
|
|
||||||
Teensy GND <-> Keyboard GND
|
|
||||||
|
|
||||||
### Pro Micro
|
|
||||||
|
|
||||||
Pro Micro 10 (B6) <-> Keyboard RESET
|
|
||||||
Pro Micro 15 (B1) <-> Keyboard B1 (SCLK)
|
|
||||||
Pro Micro 16 (B2) <-> Keyboard B2 (MOSI)
|
|
||||||
Pro Micro 14 (B3) <-> Keyboard B3 (MISO)
|
|
||||||
Pro Micro VCC <-> Keyboard VCC
|
|
||||||
Pro Micro GND <-> Keyboard GND
|
|
||||||
|
|
||||||
## The ISP Firmware (now pre-compiled)
|
|
||||||
|
|
||||||
The only difference between the .hex files below is which pin is connected to RESET. You can use them on other boards as well, as long as you're aware of the pins being used. If for some reason neither of these pins are available, [create an issue](https://github.com/qmk/qmk_firmware/issues/new), and we can generate one for you!
|
|
||||||
|
|
||||||
* Teensy 2.0: [`util/teensy_2.0_ISP_B0.hex`](https://github.com/qmk/qmk_firmware/blob/master/util/teensy_2.0_ISP_B0.hex) (`B0`)
|
|
||||||
* Pro Micro: [`util/pro_micro_ISP_B6_10.hex`](https://github.com/qmk/qmk_firmware/blob/master/util/pro_micro_ISP_B6_10.hex) (`B6/10`)
|
|
||||||
|
|
||||||
**Flash your Teenys/Pro Micro with one of these and continue - you won't need the file after flashing your ISP device.**
|
|
||||||
|
|
||||||
## Just the Bootloader File
|
|
||||||
|
|
||||||
If you just want to get things back to normal, you can flash only a bootloader from [`util/` folder](https://github.com/qmk/qmk_firmware/tree/master/util), and use your normal process to flash the firmware afterwards. Be sure to flash the correct bootloader for your chip:
|
|
||||||
|
|
||||||
* [`atmega32u4`](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_atmega32u4_1_0_0.hex) - Most keyboards, Planck Rev 1-5, Preonic Rev 1-2
|
|
||||||
* [`at90usb1286`](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_at90usb128x_1_0_1.hex) - Planck Light Rev 1
|
|
||||||
* [`atmega32a`](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_atmega32a_1_0_0.hex) - jj40
|
|
||||||
|
|
||||||
If you're not sure what your board uses, look in the `rules.mk` file for the keyboard in QMK. The `MCU =` line will have the value you need. It may differ between different versions of the board.
|
|
||||||
|
|
||||||
### Advanced/Production Techniques
|
|
||||||
|
|
||||||
If you'd like to flash both the bootloader **and** the regular firmware at the same time, you need to combine the files.
|
|
||||||
|
|
||||||
1. Open the original firmware .hex file in a text editor
|
|
||||||
2. Remove the last line (which should be `:00000001FF` - this is an EOF message)
|
|
||||||
3. Copy the entire bootloader's contents onto a new line (with no empty lines between) and paste it at the end of the original file
|
|
||||||
4. Save it as a new file by naming it `<keyboard>_<keymap>_production.hex`
|
|
||||||
|
|
||||||
It's possible to use other bootloaders here in the same way, but __you need a bootloader__, otherwise you'll have to use ISP again to write new firmware to your keyboard.
|
|
||||||
|
|
||||||
## Flashing Your Bootloader/Production File
|
|
||||||
|
|
||||||
Make sure your keyboard is unplugged from any device, and plug in your Teensy.
|
|
||||||
|
|
||||||
### QMK Toolbox
|
|
||||||
|
|
||||||
1. `AVRISP device connected` will show up in yellow
|
|
||||||
2. Select the correct bootloader/production .hex file with the `Open` dialog (spaces can't be in the path)
|
|
||||||
3. Be sure the correct `Microcontroller` option is selected
|
|
||||||
4. Hit `Flash`
|
|
||||||
5. Wait, as nothing will output for a while, especially with production files
|
|
||||||
|
|
||||||
If the verification and fuse checks are ok, you're done! Your board may restart automatically, otherwise, unplug your Teensy and plug in your keyboard - you can leave your Teensy wired to your keyboard while testing things, but it's recommended that you desolder it/remove the wiring once you're sure everything works.
|
|
||||||
|
|
||||||
### Command Line
|
|
||||||
|
|
||||||
Open `cmd` and navigate to your where your modified .hex file is. We'll pretend this file is called `main.hex`, and that your Teensy 2.0 is on the `COM3` port - if you're unsure, you can open your Device Manager, and look for `Ports > USB Serial Device`. Use that COM port here. You can confirm it's the right port with:
|
|
||||||
|
|
||||||
avrdude -c avrisp -P COM3 -p atmega32u4
|
|
||||||
|
|
||||||
and you should get something like the following output:
|
|
||||||
|
|
||||||
avrdude: AVR device initialized and ready to accept instructions
|
|
||||||
|
|
||||||
Reading | ################################################## | 100% 0.02s
|
|
||||||
|
|
||||||
avrdude: Device signature = 0x1e9587
|
|
||||||
|
|
||||||
avrdude: safemode: Fuses OK
|
|
||||||
|
|
||||||
avrdude done. Thank you.
|
|
||||||
|
|
||||||
Since our keyboard uses an `atmega32u4` (common), that is the chip we'll specify. This is the full command:
|
|
||||||
|
|
||||||
avrdude -c avrisp -P COM3 -p atmega32u4 -U flash:w:main.hex:i
|
|
||||||
|
|
||||||
If your board uses an `atmega32a` (e.g. on a jj40), the command is this (the extra code at the end sets the fuses correctly):
|
|
||||||
|
|
||||||
avrdude -c avrisp -P COM3 -p atmega32 -U flash:w:main.hex:i -U hfuse:w:0xD0:m -U lfuse:w:0x0F:m
|
|
||||||
|
|
||||||
You should see a couple of progress bars, then you should see:
|
|
||||||
|
|
||||||
avrdude: verifying ...
|
|
||||||
avrdude: 32768 bytes of flash verified
|
|
||||||
|
|
||||||
avrdude: safemode: Fuses OK
|
|
||||||
|
|
||||||
avrdude done. Thank you.
|
|
||||||
|
|
||||||
Which means everything should be ok! Your board may restart automatically, otherwise, unplug your Teensy and plug in your keyboard - you can leave your Teensy wired to your keyboard while testing things, but it's recommended that you desolder it/remove the wiring once you're sure everything works.
|
|
||||||
|
|
||||||
If you have any questions/problems, feel free to [open an issue](https://github.com/qmk/qmk_firmware/issues/new)!
|
|
@ -1,456 +0,0 @@
|
|||||||
# Keycodes Overview
|
|
||||||
|
|
||||||
When defining a [keymap](keymap.md) each key needs a valid key definition. This page documents the symbols that correspond to keycodes that are available to you in QMK.
|
|
||||||
|
|
||||||
This is a reference only. Each group of keys links to the page documenting their functionality in more detail.
|
|
||||||
|
|
||||||
## [Basic Keycodes](keycodes_basic.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-----------------------|------------------------------|-----------------------------------------------|
|
|
||||||
|`KC_NO` |`XXXXXXX` |Ignore this key (NOOP) |
|
|
||||||
|`KC_TRANSPARENT` |`KC_TRNS`, `_______` |Use the next lowest non-transparent key |
|
|
||||||
|`KC_A` | |`a` and `A` |
|
|
||||||
|`KC_B` | |`b` and `B` |
|
|
||||||
|`KC_C` | |`c` and `C` |
|
|
||||||
|`KC_D` | |`d` and `D` |
|
|
||||||
|`KC_E` | |`e` and `E` |
|
|
||||||
|`KC_F` | |`f` and `F` |
|
|
||||||
|`KC_G` | |`g` and `G` |
|
|
||||||
|`KC_H` | |`h` and `H` |
|
|
||||||
|`KC_I` | |`i` and `I` |
|
|
||||||
|`KC_J` | |`j` and `J` |
|
|
||||||
|`KC_K` | |`k` and `K` |
|
|
||||||
|`KC_L` | |`l` and `L` |
|
|
||||||
|`KC_M` | |`m` and `M` |
|
|
||||||
|`KC_N` | |`n` and `N` |
|
|
||||||
|`KC_O` | |`o` and `O` |
|
|
||||||
|`KC_P` | |`p` and `P` |
|
|
||||||
|`KC_Q` | |`q` and `Q` |
|
|
||||||
|`KC_R` | |`r` and `R` |
|
|
||||||
|`KC_S` | |`s` and `S` |
|
|
||||||
|`KC_T` | |`t` and `T` |
|
|
||||||
|`KC_U` | |`u` and `U` |
|
|
||||||
|`KC_V` | |`v` and `V` |
|
|
||||||
|`KC_W` | |`w` and `W` |
|
|
||||||
|`KC_X` | |`x` and `X` |
|
|
||||||
|`KC_Y` | |`y` and `Y` |
|
|
||||||
|`KC_Z` | |`z` and `Z` |
|
|
||||||
|`KC_1` | |`1` and `!` |
|
|
||||||
|`KC_2` | |`2` and `@` |
|
|
||||||
|`KC_3` | |`3` and `#` |
|
|
||||||
|`KC_4` | |`4` and `$` |
|
|
||||||
|`KC_5` | |`5` and `%` |
|
|
||||||
|`KC_6` | |`6` and `^` |
|
|
||||||
|`KC_7` | |`7` and `&` |
|
|
||||||
|`KC_8` | |`8` and `*` |
|
|
||||||
|`KC_9` | |`9` and `(` |
|
|
||||||
|`KC_0` | |`0` and `)` |
|
|
||||||
|`KC_ENTER` |`KC_ENT` |Return (Enter) |
|
|
||||||
|`KC_ESCAPE` |`KC_ESC` |Escape |
|
|
||||||
|`KC_BSPACE` |`KC_BSPC` |Delete (Backspace) |
|
|
||||||
|`KC_TAB` | |Tab |
|
|
||||||
|`KC_SPACE` |`KC_SPC` |Spacebar |
|
|
||||||
|`KC_MINUS` |`KC_MINS` |`-` and `_` |
|
|
||||||
|`KC_EQUAL` |`KC_EQL` |`=` and `+` |
|
|
||||||
|`KC_LBRACKET` |`KC_LBRC` |`[` and `{` |
|
|
||||||
|`KC_RBRACKET` |`KC_RBRC` |`]` and `}` |
|
|
||||||
|`KC_BSLASH` |`KC_BSLS` |`\` and <code>|</code> |
|
|
||||||
|`KC_NONUS_HASH` |`KC_NUHS` |Non-US `#` and `~` |
|
|
||||||
|`KC_SCOLON` |`KC_SCLN` |`;` and `:` |
|
|
||||||
|`KC_QUOTE` |`KC_QUOT` |`'` and `"` |
|
|
||||||
|`KC_GRAVE` |`KC_GRV`, `KC_ZKHK` |<code>`</code> and `~`, JIS Zenkaku/Hankaku|
|
|
||||||
|`KC_COMMA` |`KC_COMM` |`,` and `<` |
|
|
||||||
|`KC_DOT` | |`.` and `>` |
|
|
||||||
|`KC_SLASH` |`KC_SLSH` |`/` and `?` |
|
|
||||||
|`KC_CAPSLOCK` |`KC_CLCK`, `KC_CAPS` |Caps Lock |
|
|
||||||
|`KC_F1` | |F1 |
|
|
||||||
|`KC_F2` | |F2 |
|
|
||||||
|`KC_F3` | |F3 |
|
|
||||||
|`KC_F4` | |F4 |
|
|
||||||
|`KC_F5` | |F5 |
|
|
||||||
|`KC_F6` | |F6 |
|
|
||||||
|`KC_F7` | |F7 |
|
|
||||||
|`KC_F8` | |F8 |
|
|
||||||
|`KC_F9` | |F9 |
|
|
||||||
|`KC_F10` | |F10 |
|
|
||||||
|`KC_F11` | |F11 |
|
|
||||||
|`KC_F12` | |F12 |
|
|
||||||
|`KC_PSCREEN` |`KC_PSCR` |Print Screen |
|
|
||||||
|`KC_SCROLLLOCK` |`KC_SLCK`, `KC_BRMD` |Scroll Lock, Brightness Down (macOS) |
|
|
||||||
|`KC_PAUSE` |`KC_PAUS`, `KC_BRK`, `KC_BRMU`|Pause, Brightness Up (macOS) |
|
|
||||||
|`KC_INSERT` |`KC_INS` |Insert |
|
|
||||||
|`KC_HOME` | |Home |
|
|
||||||
|`KC_PGUP` | |Page Up |
|
|
||||||
|`KC_DELETE` |`KC_DEL` |Forward Delete |
|
|
||||||
|`KC_END` | |End |
|
|
||||||
|`KC_PGDOWN` |`KC_PGDN` |Page Down |
|
|
||||||
|`KC_RIGHT` |`KC_RGHT` |Right Arrow |
|
|
||||||
|`KC_LEFT` | |Left Arrow |
|
|
||||||
|`KC_DOWN` | |Down Arrow |
|
|
||||||
|`KC_UP` | |Up Arrow |
|
|
||||||
|`KC_NUMLOCK` |`KC_NLCK` |Keypad Num Lock and Clear |
|
|
||||||
|`KC_KP_SLASH` |`KC_PSLS` |Keypad `/` |
|
|
||||||
|`KC_KP_ASTERISK` |`KC_PAST` |Keypad `*` |
|
|
||||||
|`KC_KP_MINUS` |`KC_PMNS` |Keypad `-` |
|
|
||||||
|`KC_KP_PLUS` |`KC_PPLS` |Keypad `+` |
|
|
||||||
|`KC_KP_ENTER` |`KC_PENT` |Keypad Enter |
|
|
||||||
|`KC_KP_1` |`KC_P1` |Keypad `1` and End |
|
|
||||||
|`KC_KP_2` |`KC_P2` |Keypad `2` and Down Arrow |
|
|
||||||
|`KC_KP_3` |`KC_P3` |Keypad `3` and Page Down |
|
|
||||||
|`KC_KP_4` |`KC_P4` |Keypad `4` and Left Arrow |
|
|
||||||
|`KC_KP_5` |`KC_P5` |Keypad `5` |
|
|
||||||
|`KC_KP_6` |`KC_P6` |Keypad `6` and Right Arrow |
|
|
||||||
|`KC_KP_7` |`KC_P7` |Keypad `7` and Home |
|
|
||||||
|`KC_KP_8` |`KC_P8` |Keypad `8` and Up Arrow |
|
|
||||||
|`KC_KP_9` |`KC_P9` |Keypad `9` and Page Up |
|
|
||||||
|`KC_KP_0` |`KC_P0` |Keypad `0` and Insert |
|
|
||||||
|`KC_KP_DOT` |`KC_PDOT` |Keypad `.` and Delete |
|
|
||||||
|`KC_NONUS_BSLASH` |`KC_NUBS` |Non-US `\` and <code>|</code> |
|
|
||||||
|`KC_APPLICATION` |`KC_APP` |Application (Windows Menu Key) |
|
|
||||||
|`KC_POWER` | |System Power (macOS) |
|
|
||||||
|`KC_KP_EQUAL` |`KC_PEQL` |Keypad `=` |
|
|
||||||
|`KC_F13` | |F13 |
|
|
||||||
|`KC_F14` | |F14 |
|
|
||||||
|`KC_F15` | |F15 |
|
|
||||||
|`KC_F16` | |F16 |
|
|
||||||
|`KC_F17` | |F17 |
|
|
||||||
|`KC_F18` | |F18 |
|
|
||||||
|`KC_F19` | |F19 |
|
|
||||||
|`KC_F20` | |F20 |
|
|
||||||
|`KC_F21` | |F21 |
|
|
||||||
|`KC_F22` | |F22 |
|
|
||||||
|`KC_F23` | |F23 |
|
|
||||||
|`KC_F24` | |F24 |
|
|
||||||
|`KC_EXECUTE` |`KC_EXEC` |Execute |
|
|
||||||
|`KC_HELP` | |Help |
|
|
||||||
|`KC_MENU` | |Menu |
|
|
||||||
|`KC_SELECT` |`KC_SLCT` |Select |
|
|
||||||
|`KC_STOP` | |Stop |
|
|
||||||
|`KC_AGAIN` |`KC_AGIN` |Again |
|
|
||||||
|`KC_UNDO` | |Undo |
|
|
||||||
|`KC_CUT` | |Cut |
|
|
||||||
|`KC_COPY` | |Copy |
|
|
||||||
|`KC_PASTE` |`KC_PSTE` |Paste |
|
|
||||||
|`KC_FIND` | |Find |
|
|
||||||
|`KC__MUTE` | |Mute (macOS) |
|
|
||||||
|`KC__VOLUP` | |Volume Up (macOS) |
|
|
||||||
|`KC__VOLDOWN` | |Volume Down (macOS) |
|
|
||||||
|`KC_LOCKING_CAPS` |`KC_LCAP` |Locking Caps Lock |
|
|
||||||
|`KC_LOCKING_NUM` |`KC_LNUM` |Locking Num Lock |
|
|
||||||
|`KC_LOCKING_SCROLL` |`KC_LSCR` |Locking Scroll Lock |
|
|
||||||
|`KC_KP_COMMA` |`KC_PCMM` |Keypad `,` |
|
|
||||||
|`KC_KP_EQUAL_AS400` | |Keypad `=` on AS/400 keyboards |
|
|
||||||
|`KC_INT1` |`KC_RO` |JIS `\` and `_` |
|
|
||||||
|`KC_INT2` |`KC_KANA` |JIS Katakana/Hiragana |
|
|
||||||
|`KC_INT3` |`KC_JYEN` |JIS `¥` and <code>|</code> |
|
|
||||||
|`KC_INT4` |`KC_HENK` |JIS Henkan |
|
|
||||||
|`KC_INT5` |`KC_MHEN` |JIS Muhenkan |
|
|
||||||
|`KC_INT6` | |JIS Numpad `,` |
|
|
||||||
|`KC_INT7` | |International 7 |
|
|
||||||
|`KC_INT8` | |International 8 |
|
|
||||||
|`KC_INT9` | |International 9 |
|
|
||||||
|`KC_LANG1` |`KC_HAEN` |Hangul/English |
|
|
||||||
|`KC_LANG2` |`KC_HANJ` |Hanja |
|
|
||||||
|`KC_LANG3` | |JIS Katakana |
|
|
||||||
|`KC_LANG4` | |JIS Hiragana |
|
|
||||||
|`KC_LANG5` | |JIS Zenkaku/Hankaku |
|
|
||||||
|`KC_LANG6` | |Language 6 |
|
|
||||||
|`KC_LANG7` | |Language 7 |
|
|
||||||
|`KC_LANG8` | |Language 8 |
|
|
||||||
|`KC_LANG9` | |Language 9 |
|
|
||||||
|`KC_ALT_ERASE` |`KC_ERAS` |Alternate Erase |
|
|
||||||
|`KC_SYSREQ` | |SysReq/Attention |
|
|
||||||
|`KC_CANCEL` | |Cancel |
|
|
||||||
|`KC_CLEAR` |`KC_CLR` |Clear |
|
|
||||||
|`KC_PRIOR` | |Prior |
|
|
||||||
|`KC_RETURN` | |Return |
|
|
||||||
|`KC_SEPARATOR` | |Separator |
|
|
||||||
|`KC_OUT` | |Out |
|
|
||||||
|`KC_OPER` | |Oper |
|
|
||||||
|`KC_CLEAR_AGAIN` | |Clear/Again |
|
|
||||||
|`KC_CRSEL` | |CrSel/Props |
|
|
||||||
|`KC_EXSEL` | |ExSel |
|
|
||||||
|`KC_LCTRL` |`KC_LCTL` |Left Control |
|
|
||||||
|`KC_LSHIFT` |`KC_LSFT` |Left Shift |
|
|
||||||
|`KC_LALT` | |Left Alt |
|
|
||||||
|`KC_LGUI` |`KC_LCMD`, `KC_LWIN` |Left GUI (Windows/Command/Meta key) |
|
|
||||||
|`KC_RCTRL` |`KC_RCTL` |Right Control |
|
|
||||||
|`KC_RSHIFT` |`KC_RSFT` |Right Shift |
|
|
||||||
|`KC_RALT` |`KC_ALGR` |Right Alt (AltGr) |
|
|
||||||
|`KC_RGUI` |`KC_RCMD`, `KC_RWIN` |Right GUI (Windows/Command/Meta key) |
|
|
||||||
|`KC_SYSTEM_POWER` |`KC_PWR` |System Power Down |
|
|
||||||
|`KC_SYSTEM_SLEEP` |`KC_SLEP` |System Sleep |
|
|
||||||
|`KC_SYSTEM_WAKE` |`KC_WAKE` |System Wake |
|
|
||||||
|`KC_AUDIO_MUTE` |`KC_MUTE` |Mute |
|
|
||||||
|`KC_AUDIO_VOL_UP` |`KC_VOLU` |Volume Up |
|
|
||||||
|`KC_AUDIO_VOL_DOWN` |`KC_VOLD` |Volume Down |
|
|
||||||
|`KC_MEDIA_NEXT_TRACK` |`KC_MNXT` |Next Track (Windows) |
|
|
||||||
|`KC_MEDIA_PREV_TRACK` |`KC_MPRV` |Previous Track (Windows) |
|
|
||||||
|`KC_MEDIA_STOP` |`KC_MSTP` |Stop Track (Windows) |
|
|
||||||
|`KC_MEDIA_PLAY_PAUSE` |`KC_MPLY` |Play/Pause Track |
|
|
||||||
|`KC_MEDIA_SELECT` |`KC_MSEL` |Launch Media Player (Windows) |
|
|
||||||
|`KC_MEDIA_EJECT` |`KC_EJCT` |Eject (macOS) |
|
|
||||||
|`KC_MAIL` | |Launch Mail (Windows) |
|
|
||||||
|`KC_CALCULATOR` |`KC_CALC` |Launch Calculator (Windows) |
|
|
||||||
|`KC_MY_COMPUTER` |`KC_MYCM` |Launch My Computer (Windows) |
|
|
||||||
|`KC_WWW_SEARCH` |`KC_WSCH` |Browser Search (Windows) |
|
|
||||||
|`KC_WWW_HOME` |`KC_WHOM` |Browser Home (Windows) |
|
|
||||||
|`KC_WWW_BACK` |`KC_WBAK` |Browser Back (Windows) |
|
|
||||||
|`KC_WWW_FORWARD` |`KC_WFWD` |Browser Forward (Windows) |
|
|
||||||
|`KC_WWW_STOP` |`KC_WSTP` |Browser Stop (Windows) |
|
|
||||||
|`KC_WWW_REFRESH` |`KC_WREF` |Browser Refresh (Windows) |
|
|
||||||
|`KC_WWW_FAVORITES` |`KC_WFAV` |Browser Favorites (Windows) |
|
|
||||||
|`KC_MEDIA_FAST_FORWARD`|`KC_MFFD` |Next Track (macOS) |
|
|
||||||
|`KC_MEDIA_REWIND` |`KC_MRWD` |Previous Track (macOS) |
|
|
||||||
|`KC_BRIGHTNESS_UP` |`KC_BRIU` |Brightness Up |
|
|
||||||
|`KC_BRIGHTNESS_DOWN` |`KC_BRID` |Brightness Down |
|
|
||||||
|
|
||||||
## [Quantum Keycodes](quantum_keycodes.md#qmk-keycodes)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|---------------|-----------|---------------------------------------------------------------------|
|
|
||||||
|`RESET` | |Put the keyboard into DFU mode for flashing |
|
|
||||||
|`DEBUG` | |Toggle debug mode |
|
|
||||||
|`EEPROM_RESET` |`EEP_RST` |Resets EEPROM state by reinitializing it |
|
|
||||||
|`KC_GESC` |`GRAVE_ESC`|Escape when tapped, <code>`</code> when pressed with Shift or GUI|
|
|
||||||
|`KC_LSPO` | |Left Shift when held, `(` when tapped |
|
|
||||||
|`KC_RSPC` | |Right Shift when held, `)` when tapped |
|
|
||||||
|`KC_LEAD` | |The [Leader key](feature_leader_key.md) |
|
|
||||||
|`KC_LOCK` | |The [Lock key](feature_key_lock.md) |
|
|
||||||
|`FUNC(n)` |`F(n)` |Call `fn_action(n)` (deprecated) |
|
|
||||||
|`M(n)` | |Call macro `n` |
|
|
||||||
|`MACROTAP(n)` | |Macro-tap `n` idk FIXME |
|
|
||||||
|
|
||||||
## [Audio Keys](feature_audio.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------|---------|----------------------------------|
|
|
||||||
|`AU_ON` | |Turns on Audio Feature |
|
|
||||||
|`AU_OFF` | |Turns off Audio Feature |
|
|
||||||
|`AU_TOG` | |Toggles Audio state |
|
|
||||||
|`CLICKY_TOGGLE` |`CK_TOGG`|Toggles Audio clicky mode |
|
|
||||||
|`CLICKY_UP` |`CK_UP` |Increases frequency of the clicks |
|
|
||||||
|`CLICKY_DOWN` |`CK_DOWN`|Decreases frequency of the clicks |
|
|
||||||
|`CLICKY_RESET` |`CK_RST` |Resets frequency to default |
|
|
||||||
|`MU_ON` | |Turns on Music Mode |
|
|
||||||
|`MU_OFF` | |Turns off Music Mode |
|
|
||||||
|`MU_TOG` | |Toggles Music Mode |
|
|
||||||
|`MU_MOD` | |Cycles through the music modes |
|
|
||||||
|
|
||||||
## [Backlighting](feature_backlight.md)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|---------|------------------------------------------|
|
|
||||||
|`BL_TOGG`|Turn the backlight on or off |
|
|
||||||
|`BL_STEP`|Cycle through backlight levels |
|
|
||||||
|`BL_ON` |Set the backlight to max brightness |
|
|
||||||
|`BL_OFF` |Turn the backlight off |
|
|
||||||
|`BL_INC` |Increase the backlight level |
|
|
||||||
|`BL_DEC` |Decrease the backlight level |
|
|
||||||
|`BL_BRTG`|Toggle backlight breathing |
|
|
||||||
|
|
||||||
## [Bootmagic](feature_bootmagic.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------------------------|---------|------------------------------------|
|
|
||||||
|`MAGIC_SWAP_CONTROL_CAPSLOCK` | |Swap Caps Lock and Left Control |
|
|
||||||
|`MAGIC_CAPSLOCK_TO_CONTROL` | |Treat Caps Lock as Control |
|
|
||||||
|`MAGIC_SWAP_LALT_LGUI` | |Swap Left Alt and GUI |
|
|
||||||
|`MAGIC_SWAP_RALT_RGUI` | |Swap Right Alt and GUI |
|
|
||||||
|`MAGIC_NO_GUI` | |Disable the GUI key |
|
|
||||||
|`MAGIC_SWAP_GRAVE_ESC` | |Swap <code>`</code> and Escape |
|
|
||||||
|`MAGIC_SWAP_BACKSLASH_BACKSPACE` | |Swap `\` and Backspace |
|
|
||||||
|`MAGIC_HOST_NKRO` | |Force NKRO on |
|
|
||||||
|`MAGIC_SWAP_ALT_GUI` |`AG_SWAP`|Swap Alt and GUI on both sides |
|
|
||||||
|`MAGIC_UNSWAP_CONTROL_CAPSLOCK` | |Unswap Caps Lock and Left Control |
|
|
||||||
|`MAGIC_UNCAPSLOCK_TO_CONTROL` | |Stop treating Caps Lock as Control |
|
|
||||||
|`MAGIC_UNSWAP_LALT_LGUI` | |Unswap Left Alt and GUI |
|
|
||||||
|`MAGIC_UNSWAP_RALT_RGUI` | |Unswap Right Alt and GUI |
|
|
||||||
|`MAGIC_UNNO_GUI` | |Enable the GUI key |
|
|
||||||
|`MAGIC_UNSWAP_GRAVE_ESC` | |Unswap <code>`</code> and Escape|
|
|
||||||
|`MAGIC_UNSWAP_BACKSLASH_BACKSPACE`| |Unswap `\` and Backspace |
|
|
||||||
|`MAGIC_UNHOST_NKRO` | |Force NKRO off |
|
|
||||||
|`MAGIC_UNSWAP_ALT_GUI` |`AG_NORM`|Unswap Alt and GUI on both sides |
|
|
||||||
|`MAGIC_TOGGLE_ALT_GUI` |`AG_TOGG`|Toggle Alt and GUI swap on both sides|
|
|
||||||
|`MAGIC_TOGGLE_NKRO` | |Turn NKRO on or off |
|
|
||||||
|
|
||||||
## [Bluetooth](feature_bluetooth.md)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|----------|----------------------------------------------|
|
|
||||||
|`OUT_AUTO`|Automatically switch between USB and Bluetooth|
|
|
||||||
|`OUT_USB` |USB only |
|
|
||||||
|`OUT_BT` |Bluetooth only |
|
|
||||||
|
|
||||||
## [Layer Switching](feature_advanced_keycodes.md#switching-and-toggling-layers)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|----------------|----------------------------------------------------------------------------------|
|
|
||||||
|`DF(layer)` |Set the base (default) layer |
|
|
||||||
|`MO(layer)` |Momentarily turn on `layer` when pressed (requires `KC_TRNS` on destination layer)|
|
|
||||||
|`OSL(layer)` |Momentarily activates `layer` until a key is pressed. See [One Shot Keys](https://docs.qmk.fm/#/feature_advanced_keycodes?id=one-shot-keys) for details. |
|
|
||||||
|`LM(layer, mod)`|Momentarily turn on `layer` (like MO) with `mod` active as well. Where `mod` is a mods_bit. Mods can be viewed [here](https://docs.qmk.fm/#/feature_advanced_keycodes?id=mod-tap). Example Implementation: `LM(LAYER_1, MOD_LALT)`|
|
|
||||||
|`LT(layer, kc)` |Turn on `layer` when held, `kc` when tapped |
|
|
||||||
|`TG(layer)` |Toggle `layer` on or off |
|
|
||||||
|`TO(layer)` |Turn on `layer` when pressed |
|
|
||||||
|`TT(layer)` |Normally acts like MO unless it's tapped multiple times, which toggles `layer` on |
|
|
||||||
|
|
||||||
## [Mouse Keys](feature_mouse_keys.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------|---------|---------------------------|
|
|
||||||
|`KC_MS_UP` |`KC_MS_U`|Mouse Cursor Up |
|
|
||||||
|`KC_MS_DOWN` |`KC_MS_D`|Mouse Cursor Down |
|
|
||||||
|`KC_MS_LEFT` |`KC_MS_L`|Mouse Cursor Left |
|
|
||||||
|`KC_MS_RIGHT` |`KC_MS_R`|Mouse Cursor Right |
|
|
||||||
|`KC_MS_BTN1` |`KC_BTN1`|Mouse Button 1 |
|
|
||||||
|`KC_MS_BTN2` |`KC_BTN2`|Mouse Button 2 |
|
|
||||||
|`KC_MS_BTN3` |`KC_BTN3`|Mouse Button 3 |
|
|
||||||
|`KC_MS_BTN4` |`KC_BTN4`|Mouse Button 4 |
|
|
||||||
|`KC_MS_BTN5` |`KC_BTN5`|Mouse Button 5 |
|
|
||||||
|`KC_MS_WH_UP` |`KC_WH_U`|Mouse Wheel Up |
|
|
||||||
|`KC_MS_WH_DOWN` |`KC_WH_D`|Mouse Wheel Down |
|
|
||||||
|`KC_MS_WH_LEFT` |`KC_WH_L`|Mouse Wheel Left |
|
|
||||||
|`KC_MS_WH_RIGHT`|`KC_WH_R`|Mouse Wheel Right |
|
|
||||||
|`KC_MS_ACCEL0` |`KC_ACL0`|Set mouse acceleration to 0|
|
|
||||||
|`KC_MS_ACCEL1` |`KC_ACL1`|Set mouse acceleration to 1|
|
|
||||||
|`KC_MS_ACCEL2` |`KC_ACL2`|Set mouse acceleration to 2|
|
|
||||||
|
|
||||||
## [Modifiers](feature_advanced_keycodes.md#modifier-keys)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------|-------------------------------|----------------------------------------------------|
|
|
||||||
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|
|
||||||
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|
|
||||||
|`LALT(kc)`|`A(kc)` |Hold Left Alt and press `kc` |
|
|
||||||
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|
|
||||||
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|
|
||||||
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|
|
||||||
|`RALT(kc)`|`ALGR(kc)` |Hold Right Alt and press `kc` |
|
|
||||||
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|
|
||||||
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|
|
||||||
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|
|
||||||
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|
|
||||||
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|
|
||||||
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc`|
|
|
||||||
|`KC_MEH` | |Left Control, Shift and Alt |
|
|
||||||
|`KC_HYPR` | |Left Control, Shift, Alt and GUI |
|
|
||||||
|
|
||||||
## [Mod-Tap Keys](feature_advanced_keycodes.md#mod-tap)
|
|
||||||
|
|
||||||
|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/)|
|
|
||||||
|
|
||||||
## [RGB Lighting](feature_rgblight.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-------------------|----------|--------------------------------------------------------------------|
|
|
||||||
|`RGB_TOG` | |Toggle RGB lighting on or off |
|
|
||||||
|`RGB_MODE_FORWARD` |`RGB_MOD` |Cycle through modes, reverse direction when Shift is held |
|
|
||||||
|`RGB_MODE_REVERSE` |`RGB_RMOD`|Cycle through modes in reverse, forward direction when Shift is held|
|
|
||||||
|`RGB_HUI` | |Increase hue |
|
|
||||||
|`RGB_HUD` | |Decrease hue |
|
|
||||||
|`RGB_SAI` | |Increase saturation |
|
|
||||||
|`RGB_SAD` | |Decrease saturation |
|
|
||||||
|`RGB_VAI` | |Increase value (brightness) |
|
|
||||||
|`RGB_VAD` | |Decrease value (brightness) |
|
|
||||||
|`RGB_MODE_PLAIN` |`RGB_M_P `|Static (no animation) mode |
|
|
||||||
|`RGB_MODE_BREATHE` |`RGB_M_B` |Breathing animation mode |
|
|
||||||
|`RGB_MODE_RAINBOW` |`RGB_M_R` |Rainbow animation mode |
|
|
||||||
|`RGB_MODE_SWIRL` |`RGB_M_SW`|Swirl animation mode |
|
|
||||||
|`RGB_MODE_SNAKE` |`RGB_M_SN`|Snake animation mode |
|
|
||||||
|`RGB_MODE_KNIGHT` |`RGB_M_K` |"Knight Rider" animation mode |
|
|
||||||
|`RGB_MODE_XMAS` |`RGB_M_X` |Christmas animation mode |
|
|
||||||
|`RGB_MODE_GRADIENT`|`RGB_M_G` |Static gradient animation mode |
|
|
||||||
|`RGB_MODE_RGBTEST` |`RGB_M_T` |Red,Green,Blue test animation mode |
|
|
||||||
|
|
||||||
## [RGB Matrix Lighting](feature_rgb_matrix.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-------------------|----------|--------------------------------------------------------------------|
|
|
||||||
|`RGB_TOG` | |Toggle RGB lighting on or off |
|
|
||||||
|`RGB_MODE_FORWARD` |`RGB_MOD` |Cycle through modes, reverse direction when Shift is held |
|
|
||||||
|`RGB_MODE_REVERSE` |`RGB_RMOD`|Cycle through modes in reverse, forward direction when Shift is held|
|
|
||||||
|`RGB_HUI` | |Increase hue |
|
|
||||||
|`RGB_HUD` | |Decrease hue |
|
|
||||||
|`RGB_SAI` | |Increase saturation |
|
|
||||||
|`RGB_SAD` | |Decrease saturation |
|
|
||||||
|`RGB_VAI` | |Increase value (brightness) |
|
|
||||||
|`RGB_VAD` | |Decrease value (brightness) |
|
|
||||||
|`RGB_SPI` | |Increase effect speed (does no support eeprom yet) |
|
|
||||||
|`RGB_SPD` | |Decrease effect speed (does no support eeprom yet) |
|
|
||||||
|
|
||||||
## [Thermal Printer](feature_thermal_printer.md)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|-----------|----------------------------------------|
|
|
||||||
|`PRINT_ON` |Start printing everything the user types|
|
|
||||||
|`PRINT_OFF`|Stop printing everything the user types |
|
|
||||||
|
|
||||||
## [US ANSI Shifted Symbols](keycodes_us_ansi_shifted.md)
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|------------------------|-------------------|-------------------|
|
|
||||||
|`KC_TILDE` |`KC_TILD` |`~` |
|
|
||||||
|`KC_EXCLAIM` |`KC_EXLM` |`!` |
|
|
||||||
|`KC_AT` | |`@` |
|
|
||||||
|`KC_HASH` | |`#` |
|
|
||||||
|`KC_DOLLAR` |`KC_DLR` |`$` |
|
|
||||||
|`KC_PERCENT` |`KC_PERC` |`%` |
|
|
||||||
|`KC_CIRCUMFLEX` |`KC_CIRC` |`^` |
|
|
||||||
|`KC_AMPERSAND` |`KC_AMPR` |`&` |
|
|
||||||
|`KC_ASTERISK` |`KC_ASTR` |`*` |
|
|
||||||
|`KC_LEFT_PAREN` |`KC_LPRN` |`(` |
|
|
||||||
|`KC_RIGHT_PAREN` |`KC_RPRN` |`)` |
|
|
||||||
|`KC_UNDERSCORE` |`KC_UNDS` |`_` |
|
|
||||||
|`KC_PLUS` | |`+` |
|
|
||||||
|`KC_LEFT_CURLY_BRACE` |`KC_LCBR` |`{` |
|
|
||||||
|`KC_RIGHT_CURLY_BRACE` |`KC_RCBR` |`}` |
|
|
||||||
|`KC_PIPE` | |<code>|</code>|
|
|
||||||
|`KC_COLON` |`KC_COLN` |`:` |
|
|
||||||
|`KC_DOUBLE_QUOTE` |`KC_DQUO`, `KC_DQT`|`"` |
|
|
||||||
|`KC_LEFT_ANGLE_BRACKET` |`KC_LABK`, `KC_LT` |`<` |
|
|
||||||
|`KC_RIGHT_ANGLE_BRACKET`|`KC_RABK`, `KC_GT` |`>` |
|
|
||||||
|`KC_QUESTION` |`KC_QUES` |`?` |
|
|
||||||
|
|
||||||
## [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|------------|----------------------------------|
|
|
||||||
|`OSM(mod)` |Hold `mod` for one keypress |
|
|
||||||
|`OSL(layer)`|Switch to `layer` for one keypress|
|
|
||||||
|
|
||||||
## [Swap Hands](feature_swap_hands.md)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|-----------|-------------------------------------------------------------------------|
|
|
||||||
|`SH_T(key)`|Sends `key` with a tap; momentary swap when held. |
|
|
||||||
|`SW_ON` |Turns on swapping and leaves it on. |
|
|
||||||
|`SW_OFF` |Turn off swapping and leaves it off. Good for returning to a known state.|
|
|
||||||
|`SH_MON` |Swaps hands when pressed, returns to normal when released (momentary). |
|
|
||||||
|`SH_MOFF` |Momentarily turns off swap. |
|
|
||||||
|`SH_TG` |Toggles swap on and off with every key press. |
|
|
||||||
|`SH_TT` |Toggles with a tap; momentary when held. |
|
|
||||||
|
|
||||||
## [Unicode Support](feature_unicode.md)
|
|
||||||
|
|
||||||
|Key |Description |
|
|
||||||
|-------|---------------------------------------------------------------------------|
|
|
||||||
|`UC(c)`|Send Unicode code point `c` (`UNICODE_ENABLE`) |
|
|
||||||
|`X(i)` |Send Unicode code point at index `i` in `unicode_map` (`UNICODEMAP_ENABLE`)|
|
|
@ -1,256 +0,0 @@
|
|||||||
# Basic Keycodes
|
|
||||||
|
|
||||||
The basic set of keycodes are based on the [HID Keyboard/Keypad Usage Page (0x07)](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf) with the exception of `KC_NO`, `KC_TRNS` and keycodes in the `0xA5-DF` range. See below for more details.
|
|
||||||
|
|
||||||
## Letters and Numbers
|
|
||||||
|
|
||||||
|Key |Description|
|
|
||||||
|------|-----------|
|
|
||||||
|`KC_A`|`a` and `A`|
|
|
||||||
|`KC_B`|`b` and `B`|
|
|
||||||
|`KC_C`|`c` and `C`|
|
|
||||||
|`KC_D`|`d` and `D`|
|
|
||||||
|`KC_E`|`e` and `E`|
|
|
||||||
|`KC_F`|`f` and `F`|
|
|
||||||
|`KC_G`|`g` and `G`|
|
|
||||||
|`KC_H`|`h` and `H`|
|
|
||||||
|`KC_I`|`i` and `I`|
|
|
||||||
|`KC_J`|`j` and `J`|
|
|
||||||
|`KC_K`|`k` and `K`|
|
|
||||||
|`KC_L`|`l` and `L`|
|
|
||||||
|`KC_M`|`m` and `M`|
|
|
||||||
|`KC_N`|`n` and `N`|
|
|
||||||
|`KC_O`|`o` and `O`|
|
|
||||||
|`KC_P`|`p` and `P`|
|
|
||||||
|`KC_Q`|`q` and `Q`|
|
|
||||||
|`KC_R`|`r` and `R`|
|
|
||||||
|`KC_S`|`s` and `S`|
|
|
||||||
|`KC_T`|`t` and `T`|
|
|
||||||
|`KC_U`|`u` and `U`|
|
|
||||||
|`KC_V`|`v` and `V`|
|
|
||||||
|`KC_W`|`w` and `W`|
|
|
||||||
|`KC_X`|`x` and `X`|
|
|
||||||
|`KC_Y`|`y` and `Y`|
|
|
||||||
|`KC_Z`|`z` and `Z`|
|
|
||||||
|`KC_1`|`1` and `!`|
|
|
||||||
|`KC_2`|`2` and `@`|
|
|
||||||
|`KC_3`|`3` and `#`|
|
|
||||||
|`KC_4`|`4` and `$`|
|
|
||||||
|`KC_5`|`5` and `%`|
|
|
||||||
|`KC_6`|`6` and `^`|
|
|
||||||
|`KC_7`|`7` and `&`|
|
|
||||||
|`KC_8`|`8` and `*`|
|
|
||||||
|`KC_9`|`9` and `(`|
|
|
||||||
|`KC_0`|`0` and `)`|
|
|
||||||
|
|
||||||
## F Keys
|
|
||||||
|
|
||||||
|Key |Description|
|
|
||||||
|--------|-----------|
|
|
||||||
|`KC_F1` |F1 |
|
|
||||||
|`KC_F2` |F2 |
|
|
||||||
|`KC_F3` |F3 |
|
|
||||||
|`KC_F4` |F4 |
|
|
||||||
|`KC_F5` |F5 |
|
|
||||||
|`KC_F6` |F6 |
|
|
||||||
|`KC_F7` |F7 |
|
|
||||||
|`KC_F8` |F8 |
|
|
||||||
|`KC_F9` |F9 |
|
|
||||||
|`KC_F10`|F10 |
|
|
||||||
|`KC_F11`|F11 |
|
|
||||||
|`KC_F12`|F12 |
|
|
||||||
|`KC_F13`|F13 |
|
|
||||||
|`KC_F14`|F14 |
|
|
||||||
|`KC_F15`|F15 |
|
|
||||||
|`KC_F16`|F16 |
|
|
||||||
|`KC_F17`|F17 |
|
|
||||||
|`KC_F18`|F18 |
|
|
||||||
|`KC_F19`|F19 |
|
|
||||||
|`KC_F20`|F20 |
|
|
||||||
|`KC_F21`|F21 |
|
|
||||||
|`KC_F22`|F22 |
|
|
||||||
|`KC_F23`|F23 |
|
|
||||||
|`KC_F24`|F24 |
|
|
||||||
|
|
||||||
## Punctuation
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-----------------|-------------------|-----------------------------------------------|
|
|
||||||
|`KC_ENTER` |`KC_ENT` |Return (Enter) |
|
|
||||||
|`KC_ESCAPE` |`KC_ESC` |Escape |
|
|
||||||
|`KC_BSPACE` |`KC_BSPC` |Delete (Backspace) |
|
|
||||||
|`KC_TAB` | |Tab |
|
|
||||||
|`KC_SPACE` |`KC_SPC` |Spacebar |
|
|
||||||
|`KC_MINUS` |`KC_MINS` |`-` and `_` |
|
|
||||||
|`KC_EQUAL` |`KC_EQL` |`=` and `+` |
|
|
||||||
|`KC_LBRACKET` |`KC_LBRC` |`[` and `{` |
|
|
||||||
|`KC_RBRACKET` |`KC_RBRC` |`]` and `}` |
|
|
||||||
|`KC_BSLASH` |`KC_BSLS` |`\` and <code>|</code> |
|
|
||||||
|`KC_NONUS_HASH` |`KC_NUHS` |Non-US `#` and `~` |
|
|
||||||
|`KC_SCOLON` |`KC_SCLN` |`;` and `:` |
|
|
||||||
|`KC_QUOTE` |`KC_QUOT` |`'` and `"` |
|
|
||||||
|`KC_GRAVE` |`KC_GRV`, `KC_ZKHK`|<code>`</code> and `~`, JIS Zenkaku/Hankaku|
|
|
||||||
|`KC_COMMA` |`KC_COMM` |`,` and `<` |
|
|
||||||
|`KC_DOT` | |`.` and `>` |
|
|
||||||
|`KC_SLASH` |`KC_SLSH` |`/` and `?` |
|
|
||||||
|`KC_NONUS_BSLASH`|`KC_NUBS` |Non-US `\` and <code>|</code> |
|
|
||||||
|
|
||||||
## Lock Keys
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-------------------|--------------------|------------------------------------|
|
|
||||||
|`KC_CAPSLOCK` |`KC_CLCK`, `KC_CAPS`|Caps Lock |
|
|
||||||
|`KC_SCROLLLOCK` |`KC_SLCK`, `KC_BRMD`|Scroll Lock, Brightness Down (macOS)|
|
|
||||||
|`KC_NUMLOCK` |`KC_NLCK` |Keypad Num Lock and Clear |
|
|
||||||
|`KC_LOCKING_CAPS` |`KC_LCAP` |Locking Caps Lock |
|
|
||||||
|`KC_LOCKING_NUM` |`KC_LNUM` |Locking Num Lock |
|
|
||||||
|`KC_LOCKING_SCROLL`|`KC_LSCR` |Locking Scroll Lock |
|
|
||||||
|
|
||||||
## Modifiers
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-----------|--------------------|------------------------------------|
|
|
||||||
|`KC_LCTRL` |`KC_LCTL` |Left Control |
|
|
||||||
|`KC_LSHIFT`|`KC_LSFT` |Left Shift |
|
|
||||||
|`KC_LALT` | |Left Alt |
|
|
||||||
|`KC_LGUI` |`KC_LCMD`, `KC_LWIN`|Left GUI (Windows/Command/Meta key) |
|
|
||||||
|`KC_RCTRL` |`KC_RCTL` |Right Control |
|
|
||||||
|`KC_RSHIFT`|`KC_RSFT` |Right Shift |
|
|
||||||
|`KC_RALT` |`KC_ALGR` |Right Alt (AltGr) |
|
|
||||||
|`KC_RGUI` |`KC_RCMD`, `KC_RWIN`|Right GUI (Windows/Command/Meta key)|
|
|
||||||
|
|
||||||
## International
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------|---------|-------------------------------|
|
|
||||||
|`KC_INT1` |`KC_RO` |JIS `\` and `_` |
|
|
||||||
|`KC_INT2` |`KC_KANA`|JIS Katakana/Hiragana |
|
|
||||||
|`KC_INT3` |`KC_JYEN`|JIS `¥` and <code>|</code>|
|
|
||||||
|`KC_INT4` |`KC_HENK`|JIS Henkan |
|
|
||||||
|`KC_INT5` |`KC_MHEN`|JIS Muhenkan |
|
|
||||||
|`KC_INT6` | |JIS Numpad `,` |
|
|
||||||
|`KC_INT7` | |International 7 |
|
|
||||||
|`KC_INT8` | |International 8 |
|
|
||||||
|`KC_INT9` | |International 9 |
|
|
||||||
|`KC_LANG1`|`KC_HAEN`|Hangul/English |
|
|
||||||
|`KC_LANG2`|`KC_HANJ`|Hanja |
|
|
||||||
|`KC_LANG3`| |JIS Katakana |
|
|
||||||
|`KC_LANG4`| |JIS Hiragana |
|
|
||||||
|`KC_LANG5`| |JIS Zenkaku/Hankaku |
|
|
||||||
|`KC_LANG6`| |Language 6 |
|
|
||||||
|`KC_LANG7`| |Language 7 |
|
|
||||||
|`KC_LANG8`| |Language 8 |
|
|
||||||
|`KC_LANG9`| |Language 9 |
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|------------------|------------------------------|------------------------------|
|
|
||||||
|`KC_PSCREEN` |`KC_PSCR` |Print Screen |
|
|
||||||
|`KC_PAUSE` |`KC_PAUS`, `KC_BRK`, `KC_BRMU`|Pause, Brightness Up (macOS) |
|
|
||||||
|`KC_INSERT` |`KC_INS` |Insert |
|
|
||||||
|`KC_HOME` | |Home |
|
|
||||||
|`KC_PGUP` | |Page Up |
|
|
||||||
|`KC_DELETE` |`KC_DEL` |Forward Delete |
|
|
||||||
|`KC_END` | |End |
|
|
||||||
|`KC_PGDOWN` |`KC_PGDN` |Page Down |
|
|
||||||
|`KC_RIGHT` |`KC_RGHT` |Right Arrow |
|
|
||||||
|`KC_LEFT` | |Left Arrow |
|
|
||||||
|`KC_DOWN` | |Down Arrow |
|
|
||||||
|`KC_UP` | |Up Arrow |
|
|
||||||
|`KC_APPLICATION` |`KC_APP` |Application (Windows Menu Key)|
|
|
||||||
|`KC_POWER` | |System Power (macOS/Linux) |
|
|
||||||
|`KC_EXECUTE` |`KC_EXEC` |Execute |
|
|
||||||
|`KC_HELP` | |Help |
|
|
||||||
|`KC_MENU` | |Menu |
|
|
||||||
|`KC_SELECT` |`KC_SLCT` |Select |
|
|
||||||
|`KC_STOP` | |Stop |
|
|
||||||
|`KC_AGAIN` |`KC_AGIN` |Again |
|
|
||||||
|`KC_UNDO` | |Undo |
|
|
||||||
|`KC_CUT` | |Cut |
|
|
||||||
|`KC_COPY` | |Copy |
|
|
||||||
|`KC_PASTE` |`KC_PSTE` |Paste |
|
|
||||||
|`KC_FIND` | |Find |
|
|
||||||
|`KC__MUTE` | |Mute (macOS) |
|
|
||||||
|`KC__VOLUP` | |Volume Up (macOS) |
|
|
||||||
|`KC__VOLDOWN` | |Volume Down (macOS) |
|
|
||||||
|`KC_ALT_ERASE` |`KC_ERAS` |Alternate Erase |
|
|
||||||
|`KC_SYSREQ` | |SysReq/Attention |
|
|
||||||
|`KC_CANCEL` | |Cancel |
|
|
||||||
|`KC_CLEAR` |`KC_CLR` |Clear |
|
|
||||||
|`KC_PRIOR` | |Prior |
|
|
||||||
|`KC_RETURN` | |Return |
|
|
||||||
|`KC_SEPARATOR` | |Separator |
|
|
||||||
|`KC_OUT` | |Out |
|
|
||||||
|`KC_OPER` | |Oper |
|
|
||||||
|`KC_CLEAR_AGAIN` | |Clear/Again |
|
|
||||||
|`KC_CRSEL` | |CrSel/Props |
|
|
||||||
|`KC_EXSEL` | |ExSel |
|
|
||||||
|
|
||||||
## Media Keys
|
|
||||||
|
|
||||||
These keycodes are not part of the Keyboard/Keypad usage page. The `SYSTEM_` keycodes are found in the Generic Desktop page, and the rest are located in the Consumer page.
|
|
||||||
|
|
||||||
Windows and macOS use different keycodes for "next track" and "previous track". Make sure you choose the keycode that corresponds to your OS.
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-----------------------|---------|-----------------------------|
|
|
||||||
|`KC_SYSTEM_POWER` |`KC_PWR` |System Power Down |
|
|
||||||
|`KC_SYSTEM_SLEEP` |`KC_SLEP`|System Sleep |
|
|
||||||
|`KC_SYSTEM_WAKE` |`KC_WAKE`|System Wake |
|
|
||||||
|`KC_AUDIO_MUTE` |`KC_MUTE`|Mute |
|
|
||||||
|`KC_AUDIO_VOL_UP` |`KC_VOLU`|Volume Up |
|
|
||||||
|`KC_AUDIO_VOL_DOWN` |`KC_VOLD`|Volume Down |
|
|
||||||
|`KC_MEDIA_NEXT_TRACK` |`KC_MNXT`|Next Track (Windows) |
|
|
||||||
|`KC_MEDIA_PREV_TRACK` |`KC_MPRV`|Previous Track (Windows) |
|
|
||||||
|`KC_MEDIA_STOP` |`KC_MSTP`|Stop Track (Windows) |
|
|
||||||
|`KC_MEDIA_PLAY_PAUSE` |`KC_MPLY`|Play/Pause Track |
|
|
||||||
|`KC_MEDIA_SELECT` |`KC_MSEL`|Launch Media Player (Windows)|
|
|
||||||
|`KC_MEDIA_EJECT` |`KC_EJCT`|Eject (macOS) |
|
|
||||||
|`KC_MAIL` | |Launch Mail (Windows) |
|
|
||||||
|`KC_CALCULATOR` |`KC_CALC`|Launch Calculator (Windows) |
|
|
||||||
|`KC_MY_COMPUTER` |`KC_MYCM`|Launch My Computer (Windows) |
|
|
||||||
|`KC_WWW_SEARCH` |`KC_WSCH`|Browser Search (Windows) |
|
|
||||||
|`KC_WWW_HOME` |`KC_WHOM`|Browser Home (Windows) |
|
|
||||||
|`KC_WWW_BACK` |`KC_WBAK`|Browser Back (Windows) |
|
|
||||||
|`KC_WWW_FORWARD` |`KC_WFWD`|Browser Forward (Windows) |
|
|
||||||
|`KC_WWW_STOP` |`KC_WSTP`|Browser Stop (Windows) |
|
|
||||||
|`KC_WWW_REFRESH` |`KC_WREF`|Browser Refresh (Windows) |
|
|
||||||
|`KC_WWW_FAVORITES` |`KC_WFAV`|Browser Favorites (Windows) |
|
|
||||||
|`KC_MEDIA_FAST_FORWARD`|`KC_MFFD`|Next Track (macOS) |
|
|
||||||
|`KC_MEDIA_REWIND` |`KC_MRWD`|Previous Track (macOS) |
|
|
||||||
|`KC_BRIGHTNESS_UP` |`KC_BRIU`|Brightness Up |
|
|
||||||
|`KC_BRIGHTNESS_DOWN` |`KC_BRID`|Brightness Down |
|
|
||||||
|
|
||||||
## Number Pad
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|-------------------|---------|------------------------------|
|
|
||||||
|`KC_KP_SLASH` |`KC_PSLS`|Keypad `/` |
|
|
||||||
|`KC_KP_ASTERISK` |`KC_PAST`|Keypad `*` |
|
|
||||||
|`KC_KP_MINUS` |`KC_PMNS`|Keypad `-` |
|
|
||||||
|`KC_KP_PLUS` |`KC_PPLS`|Keypad `+` |
|
|
||||||
|`KC_KP_ENTER` |`KC_PENT`|Keypad Enter |
|
|
||||||
|`KC_KP_1` |`KC_P1` |Keypad `1` and End |
|
|
||||||
|`KC_KP_2` |`KC_P2` |Keypad `2` and Down Arrow |
|
|
||||||
|`KC_KP_3` |`KC_P3` |Keypad `3` and Page Down |
|
|
||||||
|`KC_KP_4` |`KC_P4` |Keypad `4` and Left Arrow |
|
|
||||||
|`KC_KP_5` |`KC_P5` |Keypad `5` |
|
|
||||||
|`KC_KP_6` |`KC_P6` |Keypad `6` and Right Arrow |
|
|
||||||
|`KC_KP_7` |`KC_P7` |Keypad `7` and Home |
|
|
||||||
|`KC_KP_8` |`KC_P8` |Keypad `8` and Up Arrow |
|
|
||||||
|`KC_KP_9` |`KC_P9` |Keypad `9` and Page Up |
|
|
||||||
|`KC_KP_0` |`KC_P0` |Keypad `0` and Insert |
|
|
||||||
|`KC_KP_DOT` |`KC_PDOT`|Keypad `.` and Delete |
|
|
||||||
|`KC_KP_EQUAL` |`KC_PEQL`|Keypad `=` |
|
|
||||||
|`KC_KP_COMMA` |`KC_PCMM`|Keypad `,` |
|
|
||||||
|`KC_KP_EQUAL_AS400`| |Keypad `=` on AS/400 keyboards|
|
|
||||||
|
|
||||||
## Special Keys
|
|
||||||
|
|
||||||
In addition to these, keycodes in the range of `0xA5-DF` are reserved for internal use by TMK.
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|----------------|--------------------|---------------------------------------|
|
|
||||||
|`KC_NO` |`XXXXXXX` |Ignore this key (NOOP) |
|
|
||||||
|`KC_TRANSPARENT`|`KC_TRNS`, `_______`|Use the next lowest non-transparent key|
|
|
@ -1,37 +0,0 @@
|
|||||||
# US ANSI Shifted Symbols
|
|
||||||
|
|
||||||
These keycodes correspond to characters that are "shifted" on a standard US ANSI keyboard. They do not have keycodes of their own but are simply shortcuts for `LSFT(kc)`, and as such send a Left Shift with the unshifted keycode, not the symbol itself.
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
## Keycodes
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|------------------------|-------------------|-------------------|
|
|
||||||
|`KC_TILDE` |`KC_TILD` |`~` |
|
|
||||||
|`KC_EXCLAIM` |`KC_EXLM` |`!` |
|
|
||||||
|`KC_AT` | |`@` |
|
|
||||||
|`KC_HASH` | |`#` |
|
|
||||||
|`KC_DOLLAR` |`KC_DLR` |`$` |
|
|
||||||
|`KC_PERCENT` |`KC_PERC` |`%` |
|
|
||||||
|`KC_CIRCUMFLEX` |`KC_CIRC` |`^` |
|
|
||||||
|`KC_AMPERSAND` |`KC_AMPR` |`&` |
|
|
||||||
|`KC_ASTERISK` |`KC_ASTR` |`*` |
|
|
||||||
|`KC_LEFT_PAREN` |`KC_LPRN` |`(` |
|
|
||||||
|`KC_RIGHT_PAREN` |`KC_RPRN` |`)` |
|
|
||||||
|`KC_UNDERSCORE` |`KC_UNDS` |`_` |
|
|
||||||
|`KC_PLUS` | |`+` |
|
|
||||||
|`KC_LEFT_CURLY_BRACE` |`KC_LCBR` |`{` |
|
|
||||||
|`KC_RIGHT_CURLY_BRACE` |`KC_RCBR` |`}` |
|
|
||||||
|`KC_PIPE` | |<code>|</code>|
|
|
||||||
|`KC_COLON` |`KC_COLN` |`:` |
|
|
||||||
|`KC_DOUBLE_QUOTE` |`KC_DQUO`, `KC_DQT`|`"` |
|
|
||||||
|`KC_LEFT_ANGLE_BRACKET` |`KC_LABK`, `KC_LT` |`<` |
|
|
||||||
|`KC_RIGHT_ANGLE_BRACKET`|`KC_RABK`, `KC_GT` |`>` |
|
|
||||||
|`KC_QUESTION` |`KC_QUES` |`?` |
|
|
@ -1,171 +0,0 @@
|
|||||||
# Keymap Overview
|
|
||||||
|
|
||||||
QMK keymaps are defined inside a C source file. The data structure is an array of arrays. The outer array is a list of layer arrays while the inner layer array is a list of keys. Most keyboards define a `LAYOUT()` macro to help you create this array of arrays.
|
|
||||||
|
|
||||||
|
|
||||||
## Keymap and Layers
|
|
||||||
In QMK, **`const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS]`** holds multiple **layers** of keymap information in **16 bit** data holding the **action code**. You can define **32 layers** at most.
|
|
||||||
|
|
||||||
For trivial key definitions, the higher 8 bits of the **action code** are all 0 and the lower 8 bits holds the USB HID usage code generated by the key as **keycode**.
|
|
||||||
|
|
||||||
Respective layers can be validated simultaneously. Layers are indexed with 0 to 31 and higher layer has precedence.
|
|
||||||
|
|
||||||
Keymap: 32 Layers Layer: action code matrix
|
|
||||||
----------------- ---------------------
|
|
||||||
stack of layers array_of_action_code[row][column]
|
|
||||||
____________ precedence _______________________
|
|
||||||
/ / | high / ESC / F1 / F2 / F3 ....
|
|
||||||
31 /___________// | /-----/-----/-----/-----
|
|
||||||
30 /___________// | / TAB / Q / W / E ....
|
|
||||||
29 /___________/ | /-----/-----/-----/-----
|
|
||||||
: _:_:_:_:_:__ | : /LCtrl/ A / S / D ....
|
|
||||||
: / : : : : : / | : / : : : :
|
|
||||||
2 /___________// | 2 `--------------------------
|
|
||||||
1 /___________// | 1 `--------------------------
|
|
||||||
0 /___________/ V low 0 `--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Sometimes, the action code stored in keymap may be referred as keycode in some documents due to the TMK history.
|
|
||||||
|
|
||||||
### Keymap Layer Status
|
|
||||||
The state of the Keymap layer is determined by two 32 bit parameters:
|
|
||||||
|
|
||||||
* **`default_layer_state`** indicates a base keymap layer (0-31) which is always valid and to be referred (the default layer).
|
|
||||||
* **`layer_state`** has current on/off status of each layer in its bits.
|
|
||||||
|
|
||||||
Keymap layer '0' is usually the `default_layer`, with other layers initially off after booting up the firmware, although this can configured differently in `config.h`. It is useful to change `default_layer` when you completely switch a key layout, for example, if you want to switch to Colemak instead of Qwerty.
|
|
||||||
|
|
||||||
Initial state of Keymap Change base layout
|
|
||||||
----------------------- ------------------
|
|
||||||
|
|
||||||
31 31
|
|
||||||
30 30
|
|
||||||
29 29
|
|
||||||
: :
|
|
||||||
: : ____________
|
|
||||||
2 ____________ 2 / /
|
|
||||||
1 / / ,->1 /___________/
|
|
||||||
,->0 /___________/ | 0
|
|
||||||
| |
|
|
||||||
`--- default_layer = 0 `--- default_layer = 1
|
|
||||||
layer_state = 0x00000001 layer_state = 0x00000002
|
|
||||||
|
|
||||||
On the other hand, you can change `layer_state` to overlay the base layer with other layers for features such as navigation keys, function keys (F1-F12), media keys, and/or special actions.
|
|
||||||
|
|
||||||
Overlay feature layer
|
|
||||||
--------------------- bit|status
|
|
||||||
____________ ---+------
|
|
||||||
31 / / 31 | 0
|
|
||||||
30 /___________// -----> 30 | 1
|
|
||||||
29 /___________/ -----> 29 | 1
|
|
||||||
: : | :
|
|
||||||
: ____________ : | :
|
|
||||||
2 / / 2 | 0
|
|
||||||
,->1 /___________/ -----> 1 | 1
|
|
||||||
| 0 0 | 0
|
|
||||||
| +
|
|
||||||
`--- default_layer = 1 |
|
|
||||||
layer_state = 0x60000002 <-'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Layer Precedence and Transparency
|
|
||||||
Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.
|
|
||||||
|
|
||||||
You can place `KC_TRANS` on overlay layer changes just part of layout to fall back on lower or base layer.
|
|
||||||
Key with `KC_TRANS` (`KC_TRNS` and `_______` are the alias) doesn't has its own keycode and refers to lower valid layers for keycode, instead.
|
|
||||||
|
|
||||||
## Anatomy of a `keymap.c`
|
|
||||||
|
|
||||||
For this example we will walk through an [older version of the default Clueboard 66% keymap](https://github.com/qmk/qmk_firmware/blob/ca01d94005f67ec4fa9528353481faa622d949ae/keyboards/clueboard/keymaps/default/keymap.c). You'll find it helpful to open that file in another browser window so you can look at everything in context.
|
|
||||||
|
|
||||||
There are 3 main sections of a `keymap.c` file you'll want to concern yourself with:
|
|
||||||
|
|
||||||
* [The Definitions](#definitions)
|
|
||||||
* [The Layer/Keymap Datastructure](#layers-and-keymaps)
|
|
||||||
* [Custom Functions](#custom-functions), if any
|
|
||||||
|
|
||||||
### Definitions
|
|
||||||
|
|
||||||
At the top of the file you'll find this:
|
|
||||||
|
|
||||||
#include QMK_KEYBOARD_H
|
|
||||||
|
|
||||||
// Helpful defines
|
|
||||||
#define GRAVE_MODS (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)|MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)|MOD_BIT(KC_LALT)|MOD_BIT(KC_RALT))
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
* You can use _______ in place for KC_TRNS (transparent) *
|
|
||||||
* Or you can use XXXXXXX for KC_NO (NOOP) *
|
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
// Each layer gets a name for readability.
|
|
||||||
// The underscores don't mean anything - you can
|
|
||||||
// have a layer called STUFF or any other name.
|
|
||||||
// Layer names don't all need to be of the same
|
|
||||||
// length, and you can also skip them entirely
|
|
||||||
// and just use numbers.
|
|
||||||
#define _BL 0
|
|
||||||
#define _FL 1
|
|
||||||
#define _CL 2
|
|
||||||
|
|
||||||
These are some handy definitions we can use when building our keymap and our custom function. The `GRAVE_MODS` definition will be used later in our custom function, and the following `_BL`, `_FL`, and `_CL` defines make it easier to refer to each of our layers.
|
|
||||||
|
|
||||||
Note: You may also find some older keymap files may also have a define(s) for `_______` and/or `XXXXXXX`. These can be used in place for `KC_TRNS` and `KC_NO` respectively, making it easier to see what keys a layer is overriding. These definitions are now unecessary, as they are included by default.
|
|
||||||
|
|
||||||
### Layers and Keymaps
|
|
||||||
|
|
||||||
The main part of this file is the `keymaps[]` definition. This is where you list your layers and the contents of those layers. This part of the file begins with this definition:
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
|
|
||||||
After this you'll find a list of LAYOUT() macros. A LAYOUT() is simply a list of keys to define a single layer. Typically you'll have one or more "base layers" (such as QWERTY, Dvorak, or Colemak) and then you'll layer on top of that one or more "function" layers. Due to the way layers are processed you can't overlay a "lower" layer on top of a "higher" layer.
|
|
||||||
|
|
||||||
`keymaps[][MATRIX_ROWS][MATRIX_COLS]` in QMK holds the 16 bit action code (sometimes referred as the quantum keycode) in it. For the keycode representing typical keys, its high byte is 0 and its low byte is the USB HID usage ID for keyboard.
|
|
||||||
|
|
||||||
> TMK from which QMK was forked uses `const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS]` instead and holds the 8 bit keycode. Some keycode values are reserved to induce execution of certain action codes via the `fn_actions[]` array.
|
|
||||||
|
|
||||||
#### Base Layer
|
|
||||||
|
|
||||||
Here is an example of the Clueboard's base layer:
|
|
||||||
|
|
||||||
/* Keymap _BL: Base Layer (Default Layer)
|
|
||||||
*/
|
|
||||||
[_BL] = LAYOUT(
|
|
||||||
F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP, \
|
|
||||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN, \
|
|
||||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, \
|
|
||||||
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RO, KC_RSFT, KC_UP, \
|
|
||||||
KC_LCTL, KC_LGUI, KC_LALT, KC_MHEN, KC_SPC,KC_SPC, KC_HENK, KC_RALT, KC_RCTL, MO(_FL), KC_LEFT, KC_DOWN, KC_RGHT),
|
|
||||||
|
|
||||||
Some interesting things to note about this:
|
|
||||||
|
|
||||||
* From a C source point of view it's only a single array, but we have embedded whitespace to more easily visualize where each key is on the physical device.
|
|
||||||
* Plain keyboard scancodes are prefixed with KC_, while "special" keys are not.
|
|
||||||
* The upper left key activates custom function 0 (`F(0)`)
|
|
||||||
* The "Fn" key is defined with `MO(_FL)`, which moves to the `_FL` layer while that key is being held down.
|
|
||||||
|
|
||||||
#### Function Overlay Layer
|
|
||||||
|
|
||||||
Our function layer is, from a code point of view, no different from the base layer. Conceptually, however, you will build that layer as an overlay, not a replacement. For many people this distinction does not matter, but as you build more complicated layering setups it matters more and more.
|
|
||||||
|
|
||||||
[_FL] = LAYOUT(
|
|
||||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_DEL, BL_STEP, \
|
|
||||||
_______, _______, _______,_______,_______,_______,_______,_______,KC_PSCR,KC_SLCK, KC_PAUS, _______, _______, _______, _______, \
|
|
||||||
_______, _______, MO(_CL),_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, \
|
|
||||||
_______, _______, _______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______, _______, KC_PGUP, \
|
|
||||||
_______, _______, _______, _______, _______,_______, _______, _______, _______, MO(_FL), KC_HOME, KC_PGDN, KC_END),
|
|
||||||
|
|
||||||
Some interesting things to note:
|
|
||||||
|
|
||||||
* We have used our `_______` definition to turn `KC_TRNS` into `_______`. This makes it easier to spot the keys that have changed on this layer.
|
|
||||||
* While in this layer if you press one of the `_______` keys it will activate the key in the next lowest active layer.
|
|
||||||
|
|
||||||
# Nitty Gritty Details
|
|
||||||
|
|
||||||
This should have given you a basic overview for creating your own keymap. For more details see the following resources:
|
|
||||||
|
|
||||||
* [Keycodes](keycodes.md)
|
|
||||||
* [Keymap FAQ](faq_keymap.md)
|
|
||||||
|
|
||||||
We are actively working to improve these docs. If you have suggestions for how they could be made better please [file an issue](https://github.com/qmk/qmk_firmware/issues/new)!
|
|
@ -1,163 +0,0 @@
|
|||||||
# Best Practices
|
|
||||||
|
|
||||||
## Or, "How I Learned to Stop Worrying and Love Git."
|
|
||||||
|
|
||||||
This document aims to instruct novices in the best ways to have a smooth experience in contributing to QMK. We will walk through the process of contributing to QMK, detailing some ways to make this task easier, and then later we'll break some things in order to teach you how to fix them.
|
|
||||||
|
|
||||||
This document assumes a few things:
|
|
||||||
|
|
||||||
1. You have a GitHub account, and have [forked the qmk_firmware repository](getting_started_github.md) to your account.
|
|
||||||
2. You've [set up your build environment](newbs_getting_started.md?id=environment-setup).
|
|
||||||
|
|
||||||
|
|
||||||
## Your fork's master: Update Often, Commit Never
|
|
||||||
|
|
||||||
It is highly recommended for QMK development, regardless of what is being done or where, to keep your `master` branch updated, but ***never*** commit to it. Instead, do all your changes in a development branch and issue pull requests from your branches when you're developing.
|
|
||||||
|
|
||||||
To reduce the chances of merge conflicts — instances where two or more users have edited the same part of a file concurrently — keep your `master` branch relatively up-to-date, and start any new developments by creating a new branch.
|
|
||||||
|
|
||||||
### Updating your master branch
|
|
||||||
|
|
||||||
To keep your `master` branch updated, it is recommended to add the QMK Firmware repository ("repo") as a remote repository in git. To do this, open your Git command line interface and enter:
|
|
||||||
|
|
||||||
```
|
|
||||||
git remote add upstream https://github.com/qmk/qmk_firmware.git
|
|
||||||
```
|
|
||||||
|
|
||||||
To verify that the repository has been added, run `git remote -v`, which should return the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git remote -v
|
|
||||||
origin https://github.com/<your_username>/qmk_firmware.git (fetch)
|
|
||||||
origin https://github.com/<your_username>/qmk_firmware.git (push)
|
|
||||||
upstream https://github.com/qmk/qmk_firmware.git (fetch)
|
|
||||||
upstream https://github.com/qmk/qmk_firmware.git (push)
|
|
||||||
```
|
|
||||||
|
|
||||||
Now that this is done, you can check for updates to the repo by running `git fetch upstream`. This retrieves the branches and tags — collectively referred to as "refs" — from the QMK repo, which now has the nickname `upstream`. We can now compare the data on our fork `origin` to that held by QMK.
|
|
||||||
|
|
||||||
To update your fork's master, run the following, hitting the Enter key after each line:
|
|
||||||
|
|
||||||
```
|
|
||||||
git checkout master
|
|
||||||
git fetch upstream
|
|
||||||
git pull upstream master
|
|
||||||
git push origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
This switches you to your `master` branch, retrieves the refs from the QMK repo, downloads the current QMK `master` branch to your computer, and then uploads it to your fork.
|
|
||||||
|
|
||||||
### Making Changes
|
|
||||||
|
|
||||||
To make changes, create a new branch by entering:
|
|
||||||
|
|
||||||
```
|
|
||||||
git checkout -b dev_branch
|
|
||||||
git push --set-upstream origin dev_branch
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates a new branch named `dev_branch`, checks it out, and then saves the new branch to your fork. The `--set-upstream` argument tells git to use your fork and the `dev_branch` branch every time you use `git push` or `git pull` from this branch. It only needs to be used on the first push; after that, you can safely use `git push` or `git pull`, without the rest of the arguments.
|
|
||||||
|
|
||||||
!> With `git push`, you can use `-u` in place of `--set-upstream` — `-u` is an alias for `--set-upstream`.
|
|
||||||
|
|
||||||
You can name your branch nearly anything you want, though it is recommended to name it something related to the changes you are going to make.
|
|
||||||
|
|
||||||
By default `git checkout -b` will base your new branch on the branch that is checked out. You can base your new branch on an existing branch that is not checked out by adding the name of the existing branch to the command:
|
|
||||||
|
|
||||||
```
|
|
||||||
git checkout -b dev_branch master
|
|
||||||
```
|
|
||||||
|
|
||||||
Now that you have a development branch, open your text editor and make whatever changes you need to make. It is recommended to make many small commits to your branch; that way, any change that causes issues can be more easily traced and undone if needed. To make your changes, edit and save any files that need to be updated, add them to Git's *staging area*, and then commit them to your branch:
|
|
||||||
|
|
||||||
```
|
|
||||||
git add path/to/updated_file
|
|
||||||
git commit -m "My commit message."
|
|
||||||
```
|
|
||||||
|
|
||||||
`git add` adds files that have been changed to Git's *staging area*, which is Git's "loading zone." This contains the changes that are going to be *committed* by `git commit`, which saves the changes to the repo. Use descriptive commit messages so you can know what was changed at a glance.
|
|
||||||
|
|
||||||
!> If you've changed a lot of files, but all the files are part of the same change, you can use `git add .` to add all the changed files that are in your current directory, rather than having to add each file individually.
|
|
||||||
|
|
||||||
### Publishing Your Changes
|
|
||||||
|
|
||||||
The last step is to push your changes to your fork. To do this, enter `git push`. Git now publishes the current state of `dev_branch` to your fork.
|
|
||||||
|
|
||||||
|
|
||||||
## Resolving Merge Conflicts
|
|
||||||
|
|
||||||
Sometimes when your work in a branch takes a long time to complete, changes that have been made by others conflict with changes you have made to your branch when you open a pull request. This is called a *merge conflict*, and is what happens when multiple people edit the same parts of the same files.
|
|
||||||
|
|
||||||
### Rebasing Your Changes
|
|
||||||
|
|
||||||
A *rebase* is Git's way of taking changes that were applied at one point, reversing them, and then applying the same changes to another point. In the case of a merge conflict, you can rebase your branch to grab the changes that were made between when you created your branch and the present time.
|
|
||||||
|
|
||||||
To start, run the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
git fetch upstream
|
|
||||||
git rev-list --left-right --count HEAD...upstream/master
|
|
||||||
```
|
|
||||||
|
|
||||||
The `git rev-list` command entered here returns the number of commits that differ between the current branch and QMK's master branch. We run `git fetch` first to make sure we have the refs that represent the current state of the upstream repo. The output of the `git rev-list` command entered returns two numbers:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git rev-list --left-right --count HEAD...upstream/master
|
|
||||||
7 35
|
|
||||||
```
|
|
||||||
|
|
||||||
The first number represents the number of commits on the current branch since it was created, and the second number is the number of commits made to `upstream/master` since the current branch was created, and thus, the changes that are not recorded in the current branch.
|
|
||||||
|
|
||||||
Now that the current states of both the current branch and the upstream repo are known, we can start a rebase operation:
|
|
||||||
|
|
||||||
```
|
|
||||||
git rebase upstream/master
|
|
||||||
```
|
|
||||||
|
|
||||||
This tells Git to undo the commits on the current branch, and then reapply them against QMK's master branch.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git rebase upstream/master
|
|
||||||
First, rewinding head to replay your work on top of it...
|
|
||||||
Applying: Commit #1
|
|
||||||
Using index info to reconstruct a base tree...
|
|
||||||
M conflicting_file_1.txt
|
|
||||||
Falling back to patching base and 3-way merge...
|
|
||||||
Auto-merging conflicting_file_1.txt
|
|
||||||
CONFLICT (content): Merge conflict in conflicting_file_1.txt
|
|
||||||
error: Failed to merge in the changes.
|
|
||||||
hint: Use 'git am --show-current-patch' to see the failed patch
|
|
||||||
Patch failed at 0001 Commit #1
|
|
||||||
|
|
||||||
Resolve all conflicts manually, mark them as resolved with
|
|
||||||
"git add/rm <conflicted_files>", then run "git rebase --continue".
|
|
||||||
You can instead skip this commit: run "git rebase --skip".
|
|
||||||
To abort and get back to the state before "git rebase", run "git rebase --abort".
|
|
||||||
```
|
|
||||||
|
|
||||||
This tells us that we have a merge conflict, and gives the name of the file with the conflict. Open the conflicting file in your text editor, and somewhere in the file, you'll find something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
<<<<<<< HEAD
|
|
||||||
<p>For help with any issues, email us at support@webhost.us.</p>
|
|
||||||
=======
|
|
||||||
<p>Need help? Email support@webhost.us.</p>
|
|
||||||
>>>>>>> Commit #1
|
|
||||||
```
|
|
||||||
|
|
||||||
The line `<<<<<<< HEAD` marks the beginning of a merge conflict, and the `>>>>>>> Commit #1` line marks the end, with the conflicting sections separated by `=======`. The part on the `HEAD` side is from the QMK master version of the file, and the part marked with the commit message is from the current branch and commit.
|
|
||||||
|
|
||||||
Because Git tracks *changes to files* rather than the contents of the files directly, if Git can't find the text that was in the file previous to the commit that was made, it won't know how to edit the file. Re-editing the file will solve the conflict. Make your changes, and then save the file.
|
|
||||||
|
|
||||||
```
|
|
||||||
<p>Need help? Email support@webhost.us.</p>
|
|
||||||
```
|
|
||||||
|
|
||||||
Now run:
|
|
||||||
|
|
||||||
```
|
|
||||||
git add conflicting_file_1.txt
|
|
||||||
git rebase --continue
|
|
||||||
```
|
|
||||||
|
|
||||||
Git logs the changes to the conflicting file, and continues applying the commits from our branch until it reaches the end.
|
|
@ -1,81 +0,0 @@
|
|||||||
# Building Your First Firmware
|
|
||||||
|
|
||||||
Now that you have setup your build environment you are ready to start building custom firmware. For this section of the guide we will bounce between 3 programs- your file manager, your text editor, and your terminal window. Keep all 3 open until you are done and happy with your keyboard firmware.
|
|
||||||
|
|
||||||
If you have closed and reopened your terminal window since following the first part of the guide, don't forget to `cd qmk_firmware` so that your terminal is in the correct directory.
|
|
||||||
|
|
||||||
## Navigate To Your Keymaps Folder
|
|
||||||
|
|
||||||
Start by navigating to the `keymaps` folder for your keyboard.
|
|
||||||
|
|
||||||
?> If you are on macOS or Windows there are commands you can use to easily open the keymaps folder.
|
|
||||||
|
|
||||||
?> macOS:
|
|
||||||
|
|
||||||
open keyboards/<keyboard_folder>/keymaps
|
|
||||||
|
|
||||||
?> Windows:
|
|
||||||
|
|
||||||
start .\\keyboards\\<keyboard_folder>\\keymaps
|
|
||||||
|
|
||||||
## Create a Copy Of The `default` Keymap
|
|
||||||
|
|
||||||
Once you have the `keymaps` folder open you will want to create a copy of the `default` folder. We highly recommend you name your folder the same as your GitHub username, but you can use any name you want as long as it contains only lower case letters, numbers, and the underscore character.
|
|
||||||
|
|
||||||
To automate the process, you also have the option to run the `new_keymap.sh` script.
|
|
||||||
|
|
||||||
Navigate to the `qmk_firmware/util` directory and type the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
./new_keymap.sh <keyboard path> <username>
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, for a user named John, trying to make a new keymap for the 1up60hse, they would type in
|
|
||||||
|
|
||||||
```
|
|
||||||
./new_keymap.sh 1upkeyboards/1up60hse john
|
|
||||||
```
|
|
||||||
|
|
||||||
## Open `keymap.c` In Your Favorite Text Editor
|
|
||||||
|
|
||||||
Open up your `keymap.c`. Inside this file you'll find the structure that controls how your keyboard behaves. At the top of `keymap.c` there may be some defines and enums that make the keymap easier to read. Farther down you'll find a line that looks like this:
|
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
|
|
||||||
This line indicates the start of the list of Layers. Below that you'll find lines containing either `LAYOUT` or `KEYMAP`, and these lines indicate the start of a layer. Below that line is the list of keys that comprise a that particular layer.
|
|
||||||
|
|
||||||
!> When editing your keymap file be careful not to add or remove any commas. If you do you will prevent your firmware from compiling and it may not be easy to figure out where the extra, or missing, comma is.
|
|
||||||
|
|
||||||
## Customize The Layout To Your Liking
|
|
||||||
|
|
||||||
How to complete this step is entirely up to you. Make the one change that's been bugging you, or completely rework everything. You can remove layers if you don't need all of them, or add layers up to a total of 32. Check the following documentation to find out what you can define here:
|
|
||||||
|
|
||||||
* [Keycodes](keycodes.md)
|
|
||||||
* [Features](features.md)
|
|
||||||
* [FAQ](faq.md)
|
|
||||||
|
|
||||||
?> While you get a feel for how keymaps work, keep each change small. Bigger changes make it harder to debug any problems that arise.
|
|
||||||
|
|
||||||
## Build Your Firmware
|
|
||||||
|
|
||||||
When your changes to the keymap are complete you will need to build the firmware. To do so go back to your terminal window and run the build command:
|
|
||||||
|
|
||||||
make <my_keyboard>:<my_keymap>
|
|
||||||
|
|
||||||
For example, if your keymap is named "xyverz" and you're building a keymap for a rev5 planck, you'll use this command:
|
|
||||||
|
|
||||||
make planck/rev5:xyverz
|
|
||||||
|
|
||||||
While this compiles you will have a lot of output going to the screen informing you of what files are being compiled. It should end with output that looks similar to this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/planck_rev5_xyverz.elf [OK]
|
|
||||||
Creating load file for flashing: .build/planck_rev5_xyverz.hex [OK]
|
|
||||||
Copying planck_rev5_xyverz.hex to qmk_firmware folder [OK]
|
|
||||||
Checking file size of planck_rev5_xyverz.hex [OK]
|
|
||||||
* File size is fine - 18392/28672
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flash Your Firmware
|
|
||||||
|
|
||||||
Move on to [Flashing Firmware](newbs_flashing.md) to learn how to write your new firmware to your keyboard.
|
|
@ -1,105 +0,0 @@
|
|||||||
# QMK Configurator
|
|
||||||
|
|
||||||
The [QMK Configurator](https://config.qmk.fm) is an online graphical user interface that generates QMK Firmware hex files.
|
|
||||||
|
|
||||||
?> **Please follow these steps in order.**
|
|
||||||
|
|
||||||
Watch the [Video Tutorial](https://youtu.be/7RH-1pAbjvw)
|
|
||||||
|
|
||||||
The QMK Configurator works best with Chrome/Firefox.
|
|
||||||
|
|
||||||
|
|
||||||
!> **Files from other tools such as KLE, or kbfirmware will not be compatible with QMK Configurator. Do not load them, do not import them. QMK Configurator is a DIFFERENT tool. **
|
|
||||||
|
|
||||||
## Selecting 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.
|
|
||||||
|
|
||||||
## Selecting 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.
|
|
||||||
|
|
||||||
## Keymap Name
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Creating Your Keymap
|
|
||||||
|
|
||||||
Keycode Entry is accomplished in 3 ways.
|
|
||||||
1. Drag and dropping
|
|
||||||
2. Clicking on an empty spot on the layout and clicking the keycode you desire
|
|
||||||
3. Clicking on an empty spot on the layout, 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](https://docs.qmk.fm/#/keycodes_basic)
|
|
||||||
[Advanced Keycode Reference](https://docs.qmk.fm/#/feature_advanced_keycodes)
|
|
||||||
|
|
||||||
In the event that you can't find a layout that supports your keymap, for example three spots for spacebar, or two spots for backspace, or 2 spots for shift etc etc, Fill them ALL up.
|
|
||||||
|
|
||||||
### Example:
|
|
||||||
|
|
||||||
3 spots for spacebar: Fill them ALL with spacebar
|
|
||||||
|
|
||||||
2 spots for backspace: Fill them BOTH with backspace
|
|
||||||
|
|
||||||
2 spots for right shift: Fill them BOTH with right shift
|
|
||||||
|
|
||||||
1 spot for left shift and 1 spot for iso support: Fill them both with left shift
|
|
||||||
|
|
||||||
5 spots, but only 4 keys: Guess and check or ask someone who has done it before.
|
|
||||||
|
|
||||||
## Saving Your Keymap for Future Edits
|
|
||||||
|
|
||||||
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 as the name you chose above appended with .json.
|
|
||||||
|
|
||||||
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, there is a chance your keyboard will **explode**.
|
|
||||||
|
|
||||||
## Generating your firmware file
|
|
||||||
|
|
||||||
Press the green `Compile` button.
|
|
||||||
|
|
||||||
When the compilation is done, you will be able to press the green `Download Firmware` button.
|
|
||||||
|
|
||||||
## Flashing Your Keyboard
|
|
||||||
|
|
||||||
Please refer to [Flashing Firmware](newbs_flashing.md)
|
|
||||||
|
|
||||||
## 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 my 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 bar. The same can be done for backspace and shifts
|
|
||||||
|
|
||||||
#### What is the keycode for.......
|
|
||||||
|
|
||||||
Please see
|
|
||||||
|
|
||||||
[Basic Keycode Reference](https://docs.qmk.fm/#/keycodes_basic)
|
|
||||||
[Advanced Keycode Reference](https://docs.qmk.fm/#/feature_advanced_keycodes)
|
|
||||||
|
|
||||||
#### 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)
|
|
@ -1,307 +0,0 @@
|
|||||||
# Flashing Your Keyboard
|
|
||||||
|
|
||||||
Now that you've built a custom firmware file you'll want to flash your keyboard.
|
|
||||||
|
|
||||||
## Flashing Your Keyboard with QMK Toolbox
|
|
||||||
|
|
||||||
The simplest way to flash your keyboard will be with the [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases).
|
|
||||||
|
|
||||||
However, the QMK Toolbox is only available for Windows and macOS currently. If you're using Linux (or just wish to flash the firmware from the command line), you'll have to use the [method outlined below](newbs_flashing.md#flash-your-keyboard-from-the-command-line).
|
|
||||||
|
|
||||||
### Load The File Into QMK Toolbox
|
|
||||||
|
|
||||||
Begin by opening the QMK Toolbox application. You'll want to locate the firmware file in Finder or Explorer. Your keyboard firmware may be in one of two formats- `.hex` or `.bin`. QMK tries to copy the appropriate one for your keyboard into the root `qmk_firmware` directory.
|
|
||||||
|
|
||||||
?> If you are on Windows or macOS there are commands you can use to easily open the current firmware folder in Explorer or Finder.
|
|
||||||
|
|
||||||
?> Windows:
|
|
||||||
|
|
||||||
start .
|
|
||||||
|
|
||||||
?> macOS:
|
|
||||||
|
|
||||||
open .
|
|
||||||
|
|
||||||
The firmware file always follows this naming format:
|
|
||||||
|
|
||||||
<keyboard_name>_<keymap_name>.{bin,hex}
|
|
||||||
|
|
||||||
For example, the `plank/rev5` with a `default` keymap will have this filename:
|
|
||||||
|
|
||||||
planck_rev5_default.hex
|
|
||||||
|
|
||||||
Once you have located your firmware file drag it into the "Local file" box in QMK Toolbox, or click "Open" and navigate to where your firmware file is stored.
|
|
||||||
|
|
||||||
### Put Your Keyboard Into DFU (Bootloader) Mode
|
|
||||||
|
|
||||||
In order to flash your custom firmware you have to put your keyboard into a special flashing mode. While it is in this mode you will not be able to type or otherwise use your keyboard. It is very important that you do not unplug your keyboard or otherwise interrupt the flashing process while the firmware is being written.
|
|
||||||
|
|
||||||
Different keyboards have different ways to enter this special mode. If your PCB currently runs QMK or TMK and you have not been given specific instructions try the following, in order:
|
|
||||||
|
|
||||||
* Hold down both shift keys and press `Pause`
|
|
||||||
* Hold down both shift keys and press `B`
|
|
||||||
* Unplug your keyboard, hold down the Spacebar and `B` at the same time, plug in your keyboard and wait a second before releasing the keys
|
|
||||||
* Press the physical `RESET` button on the bottom of the PCB
|
|
||||||
* Locate header pins on the PCB labeled `BOOT0` or `RESET`, short those together while plugging your PCB in
|
|
||||||
|
|
||||||
When you are successful you will see a message similar to this in QMK Toolbox:
|
|
||||||
|
|
||||||
```
|
|
||||||
*** Clueboard - Clueboard 66% HotSwap disconnected -- 0xC1ED:0x2390
|
|
||||||
*** DFU device connected
|
|
||||||
```
|
|
||||||
|
|
||||||
### Flash Your Keyboard
|
|
||||||
|
|
||||||
Click the `Flash` button in QMK Toolbox. You will see output similar to the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
*** Clueboard - Clueboard 66% HotSwap disconnected -- 0xC1ED:0x2390
|
|
||||||
*** DFU device connected
|
|
||||||
*** Attempting to flash, please don't remove device
|
|
||||||
>>> dfu-programmer atmega32u4 erase --force
|
|
||||||
Erasing flash... Success
|
|
||||||
Checking memory from 0x0 to 0x6FFF... Empty.
|
|
||||||
>>> dfu-programmer atmega32u4 flash /Users/skully/qmk_firmware/clueboard_66_hotswap_gen1_skully.hex
|
|
||||||
Checking memory from 0x0 to 0x55FF... Empty.
|
|
||||||
0% 100% Programming 0x5600 bytes...
|
|
||||||
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] Success
|
|
||||||
0% 100% Reading 0x7000 bytes...
|
|
||||||
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] Success
|
|
||||||
Validating... Success
|
|
||||||
0x5600 bytes written into 0x7000 bytes memory (76.79%).
|
|
||||||
>>> dfu-programmer atmega32u4 reset
|
|
||||||
|
|
||||||
*** DFU device disconnected
|
|
||||||
*** Clueboard - Clueboard 66% HotSwap connected -- 0xC1ED:0x2390
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flash your Keyboard from the Command Line
|
|
||||||
|
|
||||||
First thing you'll need to know is which bootloader that your keyboard uses. There are four main bootloaders that are used, usually. Pro-Micro and clones use CATERINA, and Teensy's use Halfkay, OLKB boards use QMK-DFU, and other atmega32u4 chips use DFU.
|
|
||||||
|
|
||||||
You can find more information about the bootloaders in the [Flashing Instructions and Bootloader Information](flashing.md) page.
|
|
||||||
|
|
||||||
If you know what bootloader that you're using, then when compiling the firmware, you can actually add some extra text to the `make` command to automate the flashing process.
|
|
||||||
|
|
||||||
### DFU
|
|
||||||
|
|
||||||
For the DFU bootloader, when you're ready to compile and flash your firmware, open up your terminal window and run the build command:
|
|
||||||
|
|
||||||
make <my_keyboard>:<my_keymap>:dfu
|
|
||||||
|
|
||||||
For example, if your keymap is named "xyverz" and you're building a keymap for a rev5 planck, you'll use this command:
|
|
||||||
|
|
||||||
make planck/rev5:xyverz:dfu
|
|
||||||
|
|
||||||
Once it finishes compiling, it should output the following:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/planck_rev5_xyverz.elf [OK]
|
|
||||||
Creating load file for flashing: .build/planck_rev5_xyverz.hex [OK]
|
|
||||||
Copying planck_rev5_xyverz.hex to qmk_firmware folder [OK]
|
|
||||||
Checking file size of planck_rev5_xyverz.hex
|
|
||||||
* File size is fine - 18574/28672
|
|
||||||
```
|
|
||||||
|
|
||||||
After it gets to this point, the build script will look for the DFU bootloader every 5 seconds. It will repeat the following until the device is found or you cancel it.
|
|
||||||
|
|
||||||
dfu-programmer: no device present.
|
|
||||||
Error: Bootloader not found. Trying again in 5s.
|
|
||||||
|
|
||||||
Once it does this, you'll want to reset the controller. It should then show output similiar to this:
|
|
||||||
|
|
||||||
```
|
|
||||||
*** Attempting to flash, please don't remove device
|
|
||||||
>>> dfu-programmer atmega32u4 erase --force
|
|
||||||
Erasing flash... Success
|
|
||||||
Checking memory from 0x0 to 0x6FFF... Empty.
|
|
||||||
>>> dfu-programmer atmega32u4 flash /Users/skully/qmk_firmware/clueboard_66_hotswap_gen1_skully.hex
|
|
||||||
Checking memory from 0x0 to 0x55FF... Empty.
|
|
||||||
0% 100% Programming 0x5600 bytes...
|
|
||||||
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] Success
|
|
||||||
0% 100% Reading 0x7000 bytes...
|
|
||||||
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] Success
|
|
||||||
Validating... Success
|
|
||||||
0x5600 bytes written into 0x7000 bytes memory (76.79%).
|
|
||||||
>>> dfu-programmer atmega32u4 reset
|
|
||||||
```
|
|
||||||
|
|
||||||
If you have any issues with this, you may need to this:
|
|
||||||
|
|
||||||
sudo make <my_keyboard>:<my_keymap>:dfu
|
|
||||||
|
|
||||||
#### DFU commands
|
|
||||||
|
|
||||||
There are a number of DFU commands that you can use to flash firmware to a DFU device:
|
|
||||||
|
|
||||||
* `:dfu` - This is the normal option and waits until a DFU device is available, and then flashes the firmware. This will check every 5 seconds, to see if a DFU device has appeared.
|
|
||||||
* `:dfu-ee` - This flashes an `eep` file instead of the normal hex. This is uncommon.
|
|
||||||
* `:dfu-split-left` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Left Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._
|
|
||||||
* `:dfu-split-right` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Right Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._
|
|
||||||
|
|
||||||
|
|
||||||
### Caterina
|
|
||||||
|
|
||||||
For Arduino boards and their clones (such as the SparkFun ProMicro), when you're ready to compile and flash your firmware, open up your terminal window and run the build command:
|
|
||||||
|
|
||||||
make <my_keyboard>:<my_keymap>:avrdude
|
|
||||||
|
|
||||||
For example, if your keymap is named "xyverz" and you're building a keymap for a rev2 Lets Split, you'll use this command:
|
|
||||||
|
|
||||||
make lets_split/rev2:xyverz:avrdude
|
|
||||||
|
|
||||||
Once the firmware finishes compiling, it will output something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/lets_split_rev2_xyverz.elf [OK]
|
|
||||||
Creating load file for flashing: .build/lets_split_rev2_xyverz.hex [OK]
|
|
||||||
Checking file size of lets_split_rev2_xyverz.hex [OK]
|
|
||||||
* File size is fine - 27938/28672
|
|
||||||
Detecting USB port, reset your controller now..............
|
|
||||||
```
|
|
||||||
|
|
||||||
At this point, reset the board and then the script will detect the bootloader and then flash the board. The output should look something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Detected controller on USB port at /dev/ttyS15
|
|
||||||
|
|
||||||
Connecting to programmer: .
|
|
||||||
Found programmer: Id = "CATERIN"; type = S
|
|
||||||
Software Version = 1.0; No Hardware Version given.
|
|
||||||
Programmer supports auto addr increment.
|
|
||||||
Programmer supports buffered memory access with buffersize=128 bytes.
|
|
||||||
|
|
||||||
Programmer supports the following devices:
|
|
||||||
Device code: 0x44
|
|
||||||
|
|
||||||
avrdude.exe: AVR device initialized and ready to accept instructions
|
|
||||||
|
|
||||||
Reading | ################################################## | 100% 0.00s
|
|
||||||
|
|
||||||
avrdude.exe: Device signature = 0x1e9587 (probably m32u4)
|
|
||||||
avrdude.exe: NOTE: "flash" memory has been specified, an erase cycle will be performed
|
|
||||||
To disable this feature, specify the -D option.
|
|
||||||
avrdude.exe: erasing chip
|
|
||||||
avrdude.exe: reading input file "./.build/lets_split_rev2_xyverz.hex"
|
|
||||||
avrdude.exe: input file ./.build/lets_split_rev2_xyverz.hex auto detected as Intel Hex
|
|
||||||
avrdude.exe: writing flash (27938 bytes):
|
|
||||||
|
|
||||||
Writing | ################################################## | 100% 2.40s
|
|
||||||
|
|
||||||
avrdude.exe: 27938 bytes of flash written
|
|
||||||
avrdude.exe: verifying flash memory against ./.build/lets_split_rev2_xyverz.hex:
|
|
||||||
avrdude.exe: load data flash data from input file ./.build/lets_split_rev2_xyverz.hex:
|
|
||||||
avrdude.exe: input file ./.build/lets_split_rev2_xyverz.hex auto detected as Intel Hex
|
|
||||||
avrdude.exe: input file ./.build/lets_split_rev2_xyverz.hex contains 27938 bytes
|
|
||||||
avrdude.exe: reading on-chip flash data:
|
|
||||||
|
|
||||||
Reading | ################################################## | 100% 0.43s
|
|
||||||
|
|
||||||
avrdude.exe: verifying ...
|
|
||||||
avrdude.exe: 27938 bytes of flash verified
|
|
||||||
|
|
||||||
avrdude.exe: safemode: Fuses OK (E:CB, H:D8, L:FF)
|
|
||||||
|
|
||||||
avrdude.exe done. Thank you.
|
|
||||||
```
|
|
||||||
If you have any issues with this, you may need to this:
|
|
||||||
|
|
||||||
sudo make <my_keyboard>:<my_keymap>:avrdude
|
|
||||||
|
|
||||||
|
|
||||||
Additionally, if you want to flash multiple boards, use the following command:
|
|
||||||
|
|
||||||
make <keyboard>:<keymap>:avrdude-loop
|
|
||||||
|
|
||||||
When you're done flashing boards, you'll need to hit Ctrl + C or whatever the correct keystroke is for your operating system to break the loop.
|
|
||||||
|
|
||||||
|
|
||||||
## HalfKay
|
|
||||||
|
|
||||||
For the PJRC devices (Teensy's), when you're ready to compile and flash your firmware, open up your terminal window and run the build command:
|
|
||||||
|
|
||||||
make <my_keyboard>:<my_keymap>:teensy
|
|
||||||
|
|
||||||
For example, if your keymap is named "xyverz" and you're building a keymap for an Ergodox or Ergodox EZ, you'll use this command:
|
|
||||||
|
|
||||||
make erdogox_ez:xyverz:teensy
|
|
||||||
|
|
||||||
Once the firmware finishes compiling, it will output something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/ergodox_ez_xyverz.elf [OK]
|
|
||||||
Creating load file for flashing: .build/ergodox_ez_xyverz.hex [OK]
|
|
||||||
Checking file size of ergodox_ez_xyverz.hex [OK]
|
|
||||||
* File size is fine - 25584/32256
|
|
||||||
Teensy Loader, Command Line, Version 2.1
|
|
||||||
Read "./.build/ergodox_ez_xyverz.hex": 25584 bytes, 79.3% usage
|
|
||||||
Waiting for Teensy device...
|
|
||||||
(hint: press the reset button)
|
|
||||||
```
|
|
||||||
|
|
||||||
At this point, reset your board. Once you've done that, you'll see output like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Found HalfKay Bootloader
|
|
||||||
Read "./.build/ergodox_ez_xyverz.hex": 28532 bytes, 88.5% usage
|
|
||||||
Programming............................................................................................................................................................................
|
|
||||||
...................................................
|
|
||||||
Booting
|
|
||||||
```
|
|
||||||
|
|
||||||
## STM32 (ARM)
|
|
||||||
|
|
||||||
For a majority of ARM boards (including the Proton C, Planck Rev 6, and Preonic Rev 3), when you're ready to compile and flash your firmware, open up your terminal window and run the build command:
|
|
||||||
|
|
||||||
make <my_keyboard>:<my_keymap>:dfu-util
|
|
||||||
|
|
||||||
For example, if your keymap is named "xyverz" and you're building a keymap for the Planck Revision 6 keyboard, you'll use this command and then reboot the keyboard to the bootloader (before it finishes compiling):
|
|
||||||
|
|
||||||
make planck/rev6:xyverz:dfu-util
|
|
||||||
|
|
||||||
Once the firmware finishes compiling, it will output something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/planck_rev6_xyverz.elf [OK]
|
|
||||||
Creating binary load file for flashing: .build/planck_rev6_xyverz.bin [OK]
|
|
||||||
Creating load file for flashing: .build/planck_rev6_xyverz.hex [OK]
|
|
||||||
|
|
||||||
Size after:
|
|
||||||
text data bss dec hex filename
|
|
||||||
0 41820 0 41820 a35c .build/planck_rev6_xyverz.hex
|
|
||||||
|
|
||||||
Copying planck_rev6_xyverz.bin to qmk_firmware folder [OK]
|
|
||||||
dfu-util 0.9
|
|
||||||
|
|
||||||
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
|
|
||||||
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
|
|
||||||
This program is Free Software and has ABSOLUTELY NO WARRANTY
|
|
||||||
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
|
|
||||||
|
|
||||||
Invalid DFU suffix signature
|
|
||||||
A valid DFU suffix will be required in a future dfu-util release!!!
|
|
||||||
Opening DFU capable USB device...
|
|
||||||
ID 0483:df11
|
|
||||||
Run-time device DFU version 011a
|
|
||||||
Claiming USB DFU Interface...
|
|
||||||
Setting Alternate Setting #0 ...
|
|
||||||
Determining device status: state = dfuERROR, status = 10
|
|
||||||
dfuERROR, clearing status
|
|
||||||
Determining device status: state = dfuIDLE, status = 0
|
|
||||||
dfuIDLE, continuing
|
|
||||||
DFU mode device DFU version 011a
|
|
||||||
Device returned transfer size 2048
|
|
||||||
DfuSe interface name: "Internal Flash "
|
|
||||||
Downloading to address = 0x08000000, size = 41824
|
|
||||||
Download [=========================] 100% 41824 bytes
|
|
||||||
Download done.
|
|
||||||
File downloaded successfully
|
|
||||||
Transitioning to dfuMANIFEST state
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test It Out!
|
|
||||||
|
|
||||||
Congrats! Your custom firmware has been programmed to your keyboard!
|
|
||||||
|
|
||||||
Give it a try and make sure everything works the way you want it to. We've written [Testing and Debugging](newbs_testing_debugging.md) to round out this Newbie Guide, so head over there to learn about how to troubleshoot your custom functionality.
|
|
@ -1,102 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
Your computer keyboard has a processor inside of it, not unlike the one inside your computer. This processor runs software that is responsible for detecting button presses and sending reports about the state of the keyboard when buttons are pressed or released. QMK fills the role of that software, detecting button presses and passing that information on to the host computer. When you build your custom keymap, you are creating the equivalent of an executable program for your keyboard.
|
|
||||||
|
|
||||||
QMK tries to put a lot of power into your hands by making easy things easy, and hard things possible. You don't have to know how to program to create powerful keymaps — you only have to follow a few simple syntax rules.
|
|
||||||
|
|
||||||
# Getting Started
|
|
||||||
|
|
||||||
Before you can build keymaps, you need to install some software and set up your build environment. This only has to be done once no matter how many keyboards you plan to compile firmware for.
|
|
||||||
|
|
||||||
If you would prefer a more graphical user interface approach, please consider using the online [QMK Configurator](https://config.qmk.fm). Please refer to [Building Your First Firmware using the online GUI](newbs_building_firmware_configurator.md).
|
|
||||||
|
|
||||||
|
|
||||||
## Download Software
|
|
||||||
|
|
||||||
### Text Editor
|
|
||||||
|
|
||||||
You'll need a program that can edit and save **plain text** files. If you're on Windows you can make do with Notepad, and on Linux you can use gedit. Both of these are simple but functional text editors. On macOS, be careful with the default TextEdit app: it will not save plain text files unless you explicitly select _Make Plain Text_ from the _Format_ menu.
|
|
||||||
|
|
||||||
You can also download and install a dedicated text editor like [Sublime Text](https://www.sublimetext.com/) or [VS Code](https://code.visualstudio.com/). This is probably the best way to go regardless of platform, as these programs are specifically made for editing code.
|
|
||||||
|
|
||||||
?> Not sure which text editor to use? Laurence Bradford wrote [a great introduction](https://learntocodewith.me/programming/basics/text-editors/) to the subject.
|
|
||||||
|
|
||||||
### QMK Toolbox
|
|
||||||
|
|
||||||
QMK Toolbox is an optional graphical program for Windows and macOS that allows you to both program and debug your custom keyboard. You will likely find it invaluable for easily flashing your keyboard and viewing debug messages that it prints.
|
|
||||||
|
|
||||||
[Download the latest release here.](https://github.com/qmk/qmk_toolbox/releases/latest)
|
|
||||||
|
|
||||||
* For Windows: `qmk_toolbox.exe` (portable) or `qmk_toolbox_install.exe` (installer)
|
|
||||||
* For macOS: `QMK.Toolbox.app.zip` (portable) or `QMK.Toolbox.pkg` (installer)
|
|
||||||
|
|
||||||
## Set Up Your Environment
|
|
||||||
|
|
||||||
We've tried to make QMK as easy to set up as possible. You only have to prepare your Linux or Unix environment, then let QMK install the rest.
|
|
||||||
|
|
||||||
?> If you haven't worked with the Linux/Unix command line before, there are a few basic concepts and commands you should learn. These resources will teach you enough to be able to work with QMK:<br>
|
|
||||||
[Must Know Linux Commands](https://www.guru99.com/must-know-linux-commands.html)<br>
|
|
||||||
[Some Basic Unix Commands](https://www.tjhsst.edu/~dhyatt/superap/unixcmd.html)
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
You will need to install MSYS2 and Git.
|
|
||||||
|
|
||||||
* Follow the installation instructions on the [MSYS2 homepage](http://www.msys2.org).
|
|
||||||
* Close any open MSYS2 terminals and open a new MSYS2 MinGW 64-bit terminal.
|
|
||||||
* Install Git by running this command: `pacman -S git`.
|
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
You will need to install Homebrew. Follow the instructions on the [Homebrew homepage](https://brew.sh).
|
|
||||||
|
|
||||||
After Homebrew is installed, continue with _Set Up QMK_. In that step you will run a script that will install other packages.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
You will need to install Git. It's very likely that you already have it, but if not, one of the following commands should install it:
|
|
||||||
|
|
||||||
* Debian / Ubuntu / Devuan: `apt-get install git`
|
|
||||||
* Fedora / Red Hat / CentOS: `yum install git`
|
|
||||||
* Arch: `pacman -S git`
|
|
||||||
|
|
||||||
?> Docker is also an option on all platforms. [Click here for details.](getting_started_build_tools.md#docker)
|
|
||||||
|
|
||||||
## Set Up QMK
|
|
||||||
|
|
||||||
Once you have set up your Linux/Unix environment, you are ready to download QMK. We will do this by using Git to "clone" the QMK repository. Open a Terminal or MSYS2 MinGW window and leave it open for the remainder of this guide. Inside that window run these two commands:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone --recurse-submodules https://github.com/qmk/qmk_firmware.git
|
|
||||||
cd qmk_firmware
|
|
||||||
```
|
|
||||||
|
|
||||||
?> If you already know [how to use GitHub](getting_started_github.md), we recommend that you create and clone your own fork instead. If you don't know what that means, you can safely ignore this message.
|
|
||||||
|
|
||||||
QMK comes with a script to help you set up the rest of what you'll need. You should run it now by typing in this command:
|
|
||||||
|
|
||||||
util/qmk_install.sh
|
|
||||||
|
|
||||||
## Test Your Build Environment
|
|
||||||
|
|
||||||
Now that your QMK build environment is set up, you can build a firmware for your keyboard. Start by trying to build the keyboard's default keymap. You should be able to do that with a command in this format:
|
|
||||||
|
|
||||||
make <keyboard>:default
|
|
||||||
|
|
||||||
For example, to build a firmware for a Clueboard 66% you would use:
|
|
||||||
|
|
||||||
make clueboard/66/rev3:default
|
|
||||||
|
|
||||||
When it is done you should have a lot of output that ends similar to this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Linking: .build/clueboard_66_rev3_default.elf [OK]
|
|
||||||
Creating load file for flashing: .build/clueboard_66_rev3_default.hex [OK]
|
|
||||||
Copying clueboard_66_rev3_default.hex to qmk_firmware folder [OK]
|
|
||||||
Checking file size of clueboard_66_rev3_default.hex [OK]
|
|
||||||
* The firmware size is fine - 26356/28672 (2316 bytes free)
|
|
||||||
```
|
|
||||||
|
|
||||||
# Creating Your Keymap
|
|
||||||
|
|
||||||
You are now ready to create your own personal keymap! Move on to [Building Your First Firmware](newbs_building_firmware.md) for that.
|
|
@ -1,15 +0,0 @@
|
|||||||
# Learning Resources
|
|
||||||
|
|
||||||
These resources are aimed at giving new members in the QMK community more understanding to the information provided in the Newbs docs.
|
|
||||||
|
|
||||||
Git resources:
|
|
||||||
|
|
||||||
* [Great General Tutorial](https://www.codecademy.com/learn/learn-git)
|
|
||||||
* [Git Game To Learn From Examples](https://learngitbranching.js.org/)
|
|
||||||
* [Git Resources to Learn More About Github](getting_started_github.md)
|
|
||||||
* [Git Resources Aimed Specifically toward QMK](contributing.md)
|
|
||||||
|
|
||||||
|
|
||||||
Command Line resources:
|
|
||||||
|
|
||||||
* [Good General Tutorial on Command Line](https://www.codecademy.com/learn/learn-the-command-line)
|
|
@ -1,43 +0,0 @@
|
|||||||
# Testing and Debugging
|
|
||||||
|
|
||||||
Once you've flashed your keyboard with a custom firmware you're ready to test it out. With a little bit of luck everything will work perfectly, but if not this document will help you figure out what's wrong.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Testing your keyboard is usually pretty straightforward. Press every single key and make sure it sends the keys you expect. There are even programs that will help you make sure that no key is missed.
|
|
||||||
|
|
||||||
Note: These programs are not provided by or endorsed by QMK.
|
|
||||||
|
|
||||||
* [Switch Hitter](https://elitekeyboards.com/switchhitter.php) (Windows Only)
|
|
||||||
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Mac Only)
|
|
||||||
* [Keyboard Tester](http://www.keyboardtester.com) (Web Based)
|
|
||||||
* [Keyboard Checker](http://keyboardchecker.com) (Web Based)
|
|
||||||
|
|
||||||
## Debugging With QMK Toolbox
|
|
||||||
|
|
||||||
[QMK Toolbox](https://github.com/qmk/qmk_toolbox) will show messages from your keyboard if you have `CONSOLE_ENABLE = yes` in your `rules.mk`. By default the output is very limited, but you can turn on debug mode to increase the amount of debug output. Use the `DEBUG` keycode in your keymap, use the [Command](feature_command.md) feature to enable debug mode, or add the following code to your keymap.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void keyboard_post_init_user(void) {
|
|
||||||
// Customise these values to desired behaviour
|
|
||||||
debug_enable=true;
|
|
||||||
debug_matrix=true;
|
|
||||||
//debug_keyboard=true;
|
|
||||||
//debug_mouse=true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- FIXME: Describe the debugging messages here. -->
|
|
||||||
|
|
||||||
## Sending Your Own Debug Messages
|
|
||||||
|
|
||||||
Sometimes it's useful to print debug messages from within your [custom code](custom_quantum_functions.md). Doing so is pretty simple. Start by including `print.h` at the top of your file:
|
|
||||||
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
After that you can use a few different print functions:
|
|
||||||
|
|
||||||
* `print("string")`: Print a simple string.
|
|
||||||
* `uprintf("%s string", var)`: Print a formatted string
|
|
||||||
* `dprint("string")` Print a simple string, but only when debug mode is enabled
|
|
||||||
* `dprintf("%s string", var)`: Print a formatted string, but only when debug mode is enabled
|
|
@ -1,88 +0,0 @@
|
|||||||
# Setting up Eclipse for QMK Development
|
|
||||||
|
|
||||||
[Eclipse][1] is an open-source [Integrated Development Environment](https://en.wikipedia.org/wiki/Integrated_development_environment) (IDE) widely used for Java development, but with an extensible plugin system that allows to customize it for other languages and usages.
|
|
||||||
|
|
||||||
Using an IDE such as Eclipse provides many advantages over a plain text editor, such as:
|
|
||||||
* intelligent code completion
|
|
||||||
* convenient navigation in the code
|
|
||||||
* refactoring tools
|
|
||||||
* build automation (no need for the command-line)
|
|
||||||
* a GUI for GIT
|
|
||||||
* static code analysis
|
|
||||||
* many other tools such as debugging, code formatting, showing call hierarchies etc.
|
|
||||||
|
|
||||||
The purpose of the is page is to document how to set-up Eclipse for developing AVR software, and working on the QMK code base.
|
|
||||||
|
|
||||||
Note that this set-up has been tested on Ubuntu 16.04 only for the moment.
|
|
||||||
|
|
||||||
# Prerequisites
|
|
||||||
## Build Environment
|
|
||||||
Before starting, you must have followed the [Getting Started](README.md#getting-started) section corresponding to your system. In particular, you must have been able to build the firmware with [the `make` command](../#the-make-command).
|
|
||||||
|
|
||||||
## Java
|
|
||||||
Eclipse is a Java application, so you will need to install Java 8 or more recent to be able to run it. You may choose between the JRE or the JDK, the latter being useful if you intend to do Java development.
|
|
||||||
|
|
||||||
# Install Eclipse and Its Plugins
|
|
||||||
Eclipse comes in [several flavours](http://www.eclipse.org/downloads/eclipse-packages/) depending on the target usage that you will have. There is no package comprising the AVR stack, so we will need to start from Eclipse CDT (C/C++ Development Tooling) and install the necessary plugins.
|
|
||||||
|
|
||||||
## Download and Install Eclipse CDT
|
|
||||||
If you already have Eclipse CDT on your system, you can skip this step. However it is advised to keep it up-to-date for better support.
|
|
||||||
|
|
||||||
If you have another Eclipse package installed, it is normally possible to [install the CDT plugin over it](https://eclipse.org/cdt/downloads.php). However it is probably better to reinstall it from scratch to keep it light and avoid the clutter of tools that you don't need for the projects you will be working on.
|
|
||||||
|
|
||||||
Installation is very simple: follow the [5 Steps to Install Eclipse](https://eclipse.org/downloads/eclipse-packages/?show_instructions=TRUE), and choose **Eclipse IDE for C/C++ Developers** at Step 3.
|
|
||||||
|
|
||||||
Alternatively, you can also directly [download Eclipse IDE for C/C++ Developers](http://www.eclipse.org/downloads/eclipse-packages/) ([direct link to current version](http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neonr)) and extract the package to the location of your choice (this creates an `eclipse` folder).
|
|
||||||
|
|
||||||
## First Launch
|
|
||||||
When installation is complete, click the <kbd>Launch</kbd> button. (If you extracted the package manually, open the Eclipse installation folder and double-click the `eclipse` executable)
|
|
||||||
|
|
||||||
When you are prompted with the Workspace Selector, select a directory that will hold Eclipse metadata and usually your projects. **Do not select the `qmk_firmware` directory**, this will be the project directory. Select the parent folder instead, or another (preferably empty) folder of your choice (the default is fine if you do not use it yet).
|
|
||||||
|
|
||||||
Once started, click the <kbd>Workbench</kbd> button at the top right to switch to the workbench view (there is a also checkbox at the bottom to skip the welcome screen at startup).
|
|
||||||
|
|
||||||
## Install the Necessary Plugins
|
|
||||||
Note: you do not need to restart Eclipse after installing each plugin. Simply restart once all plugins are installed.
|
|
||||||
|
|
||||||
### [The AVR Plugin](http://avr-eclipse.sourceforge.net/)
|
|
||||||
This is the most important plugin as it will allow Eclipse to _understand_ AVR C code. Follow [the instructions for using the update site](http://avr-eclipse.sourceforge.net/wiki/index.php/Plugin_Download#Update_Site), and agree with the security warning for unsigned content.
|
|
||||||
|
|
||||||
### [ANSI Escape in Console](https://marketplace.eclipse.org/content/ansi-escape-console)
|
|
||||||
This plugin is necessary to properly display the colored build output generated by the QMK makefile.
|
|
||||||
|
|
||||||
1. Open <kbd><kbd>Help</kbd> > <kbd>Eclipse Marketplace…</kbd></kbd>
|
|
||||||
2. Search for _ANSI Escape in Console_
|
|
||||||
3. Click the <samp>Install</samp> button of the plugin
|
|
||||||
4. Follow the instructions and agree again with the security warning for unsigned content.
|
|
||||||
|
|
||||||
Once both plugins are installed, restart Eclipse as prompted.
|
|
||||||
|
|
||||||
# Configure Eclipse for QMK
|
|
||||||
## Importing the Project
|
|
||||||
1. Click <kbd><kbd>File</kbd> > <kbd>New</kbd> > <kbd>Makefile Project with Existing Code</kbd></kbd>
|
|
||||||
2. On the next screen:
|
|
||||||
* Select the directory where you cloned the repository as _Existing Code Location_;
|
|
||||||
* (Optional) Give a different name to the project¹, e.g. _QMK_ or _Quantum_;
|
|
||||||
* Select the _AVR-GCC Toolchain_;
|
|
||||||
* Keep the rest as-is and click <kbd>Finish</kbd>
|
|
||||||
|
|
||||||
![Importing QMK in Eclipse](http://i.imgur.com/oHYR1yW.png)
|
|
||||||
|
|
||||||
3. The project will now be loaded and indexed. Its files can be browsed easily through the _Project Explorer_ on the left.
|
|
||||||
|
|
||||||
¹ There might be issues for importing the project with a custom name. If it does not work properly, try leaving the default project name (i.e. the name of the directory, probably `qmk_firmware`).
|
|
||||||
|
|
||||||
## Build Your Keyboard
|
|
||||||
We will now configure a make target that cleans the project and builds the keymap of your choice.
|
|
||||||
|
|
||||||
1. On the right side of the screen, select the <kbd>Make Target</kbd> tab
|
|
||||||
2. Expand the folder structure to the keyboard of your choice, e.g. `qmk_firmware/keyboards/ergodox`
|
|
||||||
3. Right-click on the keyboard folder and select <kbd>New…</kbd> (or select the folder and click the <kbd>New Make Target</kbd> icon above the tree)
|
|
||||||
4. Choose a name for your build target, e.g. _clean \<your keymap\>_
|
|
||||||
5. Make Target: this is the arguments that you give to `make` when building from the command line. If your target name does not match these arguments, uncheck <kbd>Same as target name</kbd> and input the correct arguments, e.g. `clean <your keymap>`
|
|
||||||
6. Leave the other options checked and click <kbd>OK</kbd>. Your make target will now appear under the selected keyboard.
|
|
||||||
7. (Optional) Toggle the <kbd>Hide Empty Folders</kbd> icon button above the targets tree to only show your build target.
|
|
||||||
8. Double-click the build target you created to trigger a build.
|
|
||||||
9. Select the <kbd>Console</kbd> view at the bottom to view the running build.
|
|
||||||
|
|
||||||
[1]: https://en.wikipedia.org/wiki/Eclipse_(software)
|
|
@ -1,117 +0,0 @@
|
|||||||
# Setting up Visual Studio Code for QMK Development
|
|
||||||
|
|
||||||
[Visual Studio Code](https://code.visualstudio.com/) (VS Code) is an open-source code editor that supports many different programming languages.
|
|
||||||
|
|
||||||
Using a full-featured editor such as VS Code provides many advantages over a plain text editor, such as:
|
|
||||||
* intelligent code completion
|
|
||||||
* convenient navigation in the code
|
|
||||||
* refactoring tools
|
|
||||||
* build automation (no need for the command-line)
|
|
||||||
* a graphical front end for GIT
|
|
||||||
* many other tools such as debugging, code formatting, showing call hierarchies etc.
|
|
||||||
|
|
||||||
The purpose of this page is to document how to set up VS Code for developing QMK Firmware.
|
|
||||||
|
|
||||||
This guide covers how to configure everything needed on Windows and Ubuntu 18.04
|
|
||||||
|
|
||||||
# Set up VS Code
|
|
||||||
Before starting, you will want to make sure that you have all of the build tools set up, and QMK Firmware cloned. Head to the the [Newbs Getting Started Guide](newbs_getting_started.md) to get things set up, if you haven't already.
|
|
||||||
|
|
||||||
## Windows
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
* [Git for Windows](https://git-scm.com/download/win) (This link will prompt to save/run the installer)
|
|
||||||
|
|
||||||
1. Disable all of the options but `Git LFS (Large File Support)` and `Check daily for Git for Windows updates`.
|
|
||||||
2. Set the default editor to `Use Visual Studio Code as Git's default editor`
|
|
||||||
3. Select the `Use Git from Git Bash only` option, since that's the option that you should use here.
|
|
||||||
4. For the `Choosing HTTPS transport backend`, either option should be fine.
|
|
||||||
5. Select the `Checkout as-is, commit Unix-style line endings` option. QMK Firmware uses Unix style commits.
|
|
||||||
6. For the extra options, leave the default options as is.
|
|
||||||
|
|
||||||
This software is needed for Git support in VS Code. It may be possible to not include this, but it is much simpler to just use this.
|
|
||||||
|
|
||||||
* [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases) (Optional)
|
|
||||||
|
|
||||||
This software provides better support for Git by providing secure storage for git credentials, MFA and personal access token generation.
|
|
||||||
|
|
||||||
This isn't strictly needed, but we would recommend it.
|
|
||||||
|
|
||||||
|
|
||||||
### Installing VS Code
|
|
||||||
|
|
||||||
1. Head to [VS Code](https://code.visualstudio.com/) and download the installer
|
|
||||||
2. Run the installer
|
|
||||||
|
|
||||||
This part is super simple. However, there is some configuration that we need to do to ensure things are configured correctly.
|
|
||||||
|
|
||||||
### Configuring VS Code
|
|
||||||
|
|
||||||
First, we need to set up IntelliSense. This isn't strictly required, but it will make your life a LOT easier. To do this, we need to create the `.vscode/c_cpp_properies.json` file in the QMK Firmware folder, You can do this all manually, but I've done most of the work already.
|
|
||||||
|
|
||||||
Grab [this file](https://gist.github.com/drashna/48e2c49ce877be592a1650f91f8473e8) and save it. You may need to edit this file, if you didn't install MSYS2 to the default location, or are using WSL/LxSS.
|
|
||||||
|
|
||||||
Once you have saved this file, you will need to reload VS Code, if it was already running.
|
|
||||||
|
|
||||||
?> You should see an `extensions.json` and `settings.json` file in the `.vscode` folder, as well.
|
|
||||||
|
|
||||||
|
|
||||||
Now, we will set up the MSYS2 window to show up in VSCode as the integrated terminal. This has a number of advantages. Mostly, you can control+click on errors and jump to those files. This makes debugging much easier. It's also nice, in that you don't have to jump to another window.
|
|
||||||
|
|
||||||
1. Click <kbd><kbd>File</kbd> > <kbd>Preferences ></kbd> > <kbd>Settings</kbd> </kbd>
|
|
||||||
2. Click on the <kbd>{}</kbd> button, in the top right to open the `settings.json` file.
|
|
||||||
3. Set the file's content to:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
|
|
||||||
"terminal.integrated.env.windows": {
|
|
||||||
"MSYSTEM": "MINGW64",
|
|
||||||
"CHERE_INVOKING": "1"
|
|
||||||
},
|
|
||||||
"terminal.integrated.shellArgs.windows": [
|
|
||||||
"--login"
|
|
||||||
],
|
|
||||||
"terminal.integrated.cursorStyle": "line"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If there are settings here already, then just add everything between the first and last curly brackets.
|
|
||||||
|
|
||||||
?> If you installed MSYS2 to a different folder, then you'll need to change the path for `terminal.integrated.shell.windows` to the correct path for your system.
|
|
||||||
|
|
||||||
4. Hit Ctrl-` (grave) to bring up the terminal.
|
|
||||||
|
|
||||||
This should start the terminal in the workspace's folder (so the `qmk_firmware` folder), and then you can compile your keyboard.
|
|
||||||
|
|
||||||
|
|
||||||
## Every other Operating System
|
|
||||||
|
|
||||||
1. Head to [VS Code](https://code.visualstudio.com/) and download the installer
|
|
||||||
2. Run the installer
|
|
||||||
3. That's it
|
|
||||||
|
|
||||||
No, really, that's it. The paths needed are already included when installing the packages, and it is much better about detecting the current workspace files and parsing them for IntelliSense.
|
|
||||||
|
|
||||||
## Plugins
|
|
||||||
|
|
||||||
There are a number of extensions that you may want to install:
|
|
||||||
|
|
||||||
* [Git Extension Pack](https://marketplace.visualstudio.com/items?itemName=donjayamanne.git-extension-pack) -
|
|
||||||
This installs a bunch of Git related tools that may make using Git with QMK Firmware easier.
|
|
||||||
* [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - _[Optional]_ - Helps to keep the code to the QMK Coding Conventions.
|
|
||||||
* [Bracket Pair Colorizer 2](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer-2) - _[Optional]_ - This color codes the brackets in your code, to make it easier to reference nested code.
|
|
||||||
* [Github Markdown Preview](https://marketplace.visualstudio.com/items?itemName=bierner.github-markdown-preview) - _[Optional]_ - Makes the markdown preview in VS Code more like GitHub's.
|
|
||||||
* [VS Live Share Extension Pack](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack) - _[Optional]_ - This extension allows somebody else to access your workspace (or you to access somebody else's workspace) and help out. This is great if you're having issues and need some help from somebody.
|
|
||||||
* [VIM Keymap](https://marketplace.visualstudio.com/items?itemName=GiuseppeCesarano.vim-keymap) - _[Optional]_ - For those that prefer VIM style keybindings. There are other options for this, too.
|
|
||||||
* [Travis CI Status](https://marketplace.visualstudio.com/items?itemName=felixrieseberg.vsc-travis-ci-status) - _[Optional]_ - This shows the current Travis CI status, if you have it set up.
|
|
||||||
|
|
||||||
Restart once you've installed any extensions
|
|
||||||
|
|
||||||
# Configure VS Code for QMK
|
|
||||||
1. Click <kbd><kbd>File</kbd> > <kbd>Open Folder</kbd></kbd>
|
|
||||||
2. Open the QMK Firmware folder that you cloned from GitHub.
|
|
||||||
3. Click <kbd><kbd>File</kbd> > <kbd>Save Workspace As...</kbd></kbd>
|
|
||||||
|
|
||||||
And now you're ready to code QMK Firmware in VS Code
|
|
@ -1,70 +0,0 @@
|
|||||||
Setting up your ARM based PCB is a little more involved than an Atmel MCU, but is easy enough. Start by using `util/new_project.sh <keyboard>` to create a new project:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ util/new_project.sh simontester
|
|
||||||
######################################################
|
|
||||||
# /keyboards/simontester project created. To start
|
|
||||||
# working on things, cd into keyboards/simontester
|
|
||||||
######################################################
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# END OF NEW ARM DOC, OLD ATMEL DOC FOLLOWS
|
|
||||||
|
|
||||||
## `/keyboards/<keyboard>/config.h`
|
|
||||||
|
|
||||||
The `USB Device descriptor parameter` block contains parameters are used to uniquely identify your keyboard, but they don't really matter to the machine.
|
|
||||||
|
|
||||||
Your `MATRIX_ROWS` and `MATRIX_COLS` are the numbers of rows and cols in your keyboard matrix - this may be different than the number of actual rows and columns on your keyboard. There are some tricks you can pull to increase the number of keys in a given matrix, but most keyboards are pretty straight-forward.
|
|
||||||
|
|
||||||
The `MATRIX_ROW_PINS` and `MATRIX_COL_PINS` are the pins your MCU uses on each row/column. Your schematic (if you have one) will have this information on it, and the values will vary depending on your setup. This is one of the most important things to double-check in getting your keyboard setup correctly.
|
|
||||||
|
|
||||||
For the `DIODE_DIRECTION`, most hand-wiring guides will instruct you to wire the diodes in the `COL2ROW` position, but it's possible that they are in the other - people coming from EasyAVR often use `ROW2COL`. Nothing will function if this is incorrect.
|
|
||||||
|
|
||||||
`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to. Currently only B5, B6, and B7 are supported.
|
|
||||||
|
|
||||||
`BACKLIGHT_BREATHING` is a fancier backlight feature that adds breathing/pulsing/fading effects to the backlight. It uses the same timer as the normal backlight. These breathing effects must be called by code in your keymap.
|
|
||||||
|
|
||||||
`BACKLIGHT_LEVELS` is how many levels exist for your backlight - max is 15, and they are computed automatically from this number.
|
|
||||||
|
|
||||||
## `/keyboards/<keyboard>/Makefile`
|
|
||||||
|
|
||||||
The values at the top likely won't need to be changed, since most boards use the `atmega32u4` chip. The `BOOTLOADER_SIZE` will need to be adjusted based on your MCU type. It's defaulted to the Teensy, since that's the most common controller. Below is quoted from the `Makefile`.
|
|
||||||
|
|
||||||
```
|
|
||||||
# Boot Section Size in *bytes*
|
|
||||||
# Teensy halfKay 512
|
|
||||||
# Teensy++ halfKay 1024
|
|
||||||
# Atmel DFU loader 4096
|
|
||||||
# LUFA bootloader 4096
|
|
||||||
# USBaspLoader 2048
|
|
||||||
OPT_DEFS += -DBOOTLOADER_SIZE=512
|
|
||||||
```
|
|
||||||
|
|
||||||
At the bottom of the file, you'll find lots of features to turn on and off - all of these options should be set with `?=` to allow for the keymap overrides. `?=` only assigns if the variable was previously undefined. For the full documentation of these features, see the [Makefile options](#makefile-options).
|
|
||||||
|
|
||||||
## `/keyboards/<keyboard>/readme.md`
|
|
||||||
|
|
||||||
This is where you'll describe your keyboard - please write as much as you can about it! Talking about default functionality/features is useful here. Feel free to link to external pages/sites if necessary. Images can be included here as well. This file will be rendered into a webpage at qmk.fm/keyboards/<keyboard>/.
|
|
||||||
|
|
||||||
## `/keyboards/<keyboard>/<keyboard>.c`
|
|
||||||
|
|
||||||
This is where all of the custom logic for your keyboard goes - you may not need to put anything in this file, since a lot of things are configured automatically. All of the `*_kb()` functions are defined here. If you modify them, remember to keep the calls to `*_user()`, or things in the keymaps might not work. You can read more about the functions [here](#custom-quantum-functions-for-keyboards-and-keymaps)
|
|
||||||
|
|
||||||
## `/keyboards/<keyboard>/<keyboard>.h`
|
|
||||||
|
|
||||||
Here is where you can (optionally) define your `LAYOUT` function to remap your matrix into a more readable format. With ortholinear boards, this isn't always necessary, but it can help to accommodate the dead spots on your matrix, where there are keys that take up more than one space (2u, staggering, 6.25u, etc). The example shows the difference between the physical keys, and the matrix design:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define LAYOUT( \
|
|
||||||
k00, k01, k02, \
|
|
||||||
k10, k11 \
|
|
||||||
) \
|
|
||||||
{ \
|
|
||||||
{ k00, k01, k02 }, \
|
|
||||||
{ k10, KC_NO, k11 }, \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Each of the `kxx` variables needs to be unique, and usually follows the format `k<row><col>`. You can place `KC_NO` where your dead keys are in your matrix.
|
|
@ -1,62 +0,0 @@
|
|||||||
Time to Sleep
|
|
||||||
=============
|
|
||||||
USB suspend no activity on USB line for 3ms
|
|
||||||
No Interaction no user interaction
|
|
||||||
matrix has no change
|
|
||||||
matrix has no switch on
|
|
||||||
|
|
||||||
|
|
||||||
AVR Power Management
|
|
||||||
====================
|
|
||||||
|
|
||||||
V-USB suspend
|
|
||||||
USB suspend
|
|
||||||
http://vusb.wikidot.com/examples
|
|
||||||
|
|
||||||
MCUSR MCU Status Register
|
|
||||||
WDRF Watchdog Reset Flag
|
|
||||||
BORF
|
|
||||||
EXTRF
|
|
||||||
PORF Power-on Reset Flag
|
|
||||||
|
|
||||||
SMCR Sleep Mode Control Register
|
|
||||||
SE Sleep Enable
|
|
||||||
SM2:0
|
|
||||||
#define set_sleep_mode(mode) \
|
|
||||||
#define SLEEP_MODE_IDLE (0)
|
|
||||||
#define SLEEP_MODE_ADC _BV(SM0)
|
|
||||||
#define SLEEP_MODE_PWR_DOWN _BV(SM1)
|
|
||||||
#define SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1))
|
|
||||||
#define SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2))
|
|
||||||
#define SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2))
|
|
||||||
|
|
||||||
|
|
||||||
ACSR Analog Comparator Control and Status Register
|
|
||||||
To disable Analog Comparator
|
|
||||||
ACSR = 0x80;
|
|
||||||
or
|
|
||||||
ACSR &= ~_BV(ACIE);
|
|
||||||
ACSR |= _BV(ACD);
|
|
||||||
|
|
||||||
ACD: Analog Comparator Disable
|
|
||||||
When this bit is written logic one, the power to the Analog Comparator is
|
|
||||||
switched off. This bit can be set at any time to turn off the Analog
|
|
||||||
Comparator. This will reduce power consumption in Active and Idle mode.
|
|
||||||
When changing the ACD bit, the Analog Comparator Interrupt must be disabled
|
|
||||||
by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when
|
|
||||||
the bit is changed.
|
|
||||||
|
|
||||||
DIDR1 Digital Input Disable Register 1
|
|
||||||
AIN1D
|
|
||||||
AIN0D
|
|
||||||
When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer.
|
|
||||||
|
|
||||||
|
|
||||||
PRR Power Reduction Register
|
|
||||||
PRTWI
|
|
||||||
PRTIM2
|
|
||||||
PRTIM0
|
|
||||||
PRTIM1
|
|
||||||
PRSPI
|
|
||||||
PRUSART0
|
|
||||||
PRADC
|
|
@ -1,21 +0,0 @@
|
|||||||
# Converting a board to use the Proton C
|
|
||||||
|
|
||||||
If a board currently supported in QMK uses a Pro Micro (or compatible board) and you want to use the Proton C, you can generate the firmware by appending `CONVERT_TO_PROTON_C=yes` (or `CTPC=yes`) to your make argument, like this:
|
|
||||||
|
|
||||||
make 40percentclub/mf68:default CTPC=yes
|
|
||||||
|
|
||||||
You can add the same argument to your keymap's `rules.mk`, which will accomplish the same thing.
|
|
||||||
|
|
||||||
This exposes the `CONVERT_TO_PROTON_C` flag that you can use in your code with `#ifdef`s, like this:
|
|
||||||
|
|
||||||
#ifdef CONVERT_TO_PROTON_C
|
|
||||||
// Proton C code
|
|
||||||
#else
|
|
||||||
// Pro Micro code
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Before being able to compile, you may get some errors about `PORTB/DDRB`, etc not being defined, so you'll need to convert the keyboard's code to use the [GPIO Controls](internals_gpio_control.md) that will work for both ARM and AVR. This shouldn't affect the AVR builds at all.
|
|
||||||
|
|
||||||
The Proton C only has one on-board LED (C13), and by default, the TXLED (D5) is mapped to it. If you want the RXLED (B0) mapped to it instead, add this like to your `config.h`:
|
|
||||||
|
|
||||||
#define CONVERT_TO_PROTON_C_RXLED
|
|
@ -1,862 +0,0 @@
|
|||||||
* {
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
body:not(.ready) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
body:not(.ready) [data-cloak],
|
|
||||||
body:not(.ready) .app-nav,
|
|
||||||
body:not(.ready) > nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
div#app {
|
|
||||||
font-size: 30px;
|
|
||||||
font-weight: lighter;
|
|
||||||
margin: 40vh auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
div#app:empty::before {
|
|
||||||
content: 'Loading...';
|
|
||||||
}
|
|
||||||
.emoji {
|
|
||||||
height: 1.2rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.progress {
|
|
||||||
background-color: var(--theme-color, #ea6f5a);
|
|
||||||
height: 2px;
|
|
||||||
left: 0px;
|
|
||||||
position: fixed;
|
|
||||||
right: 0px;
|
|
||||||
top: 0px;
|
|
||||||
-webkit-transition: width 0.2s, opacity 0.4s;
|
|
||||||
transition: width 0.2s, opacity 0.4s;
|
|
||||||
width: 0%;
|
|
||||||
z-index: 999999;
|
|
||||||
}
|
|
||||||
.search a:hover {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
.search .search-keyword {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
color: #efefef;
|
|
||||||
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
|
||||||
font-size: 15px;
|
|
||||||
letter-spacing: 0;
|
|
||||||
margin: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
a[disabled] {
|
|
||||||
cursor: not-allowed;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
kbd {
|
|
||||||
border: solid 1px #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 12px !important;
|
|
||||||
line-height: 12px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
padding: 3px 5px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.task-list-item {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
li input[type='checkbox'] {
|
|
||||||
margin: 0 0.2em 0.25em -1.6em;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.app-nav {
|
|
||||||
margin: 25px 60px 0 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
text-align: right;
|
|
||||||
z-index: 10;
|
|
||||||
/* navbar dropdown */
|
|
||||||
}
|
|
||||||
.app-nav.no-badge {
|
|
||||||
margin-right: 25px;
|
|
||||||
}
|
|
||||||
.app-nav p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.app-nav > a {
|
|
||||||
margin: 0 1rem;
|
|
||||||
padding: 5px 0;
|
|
||||||
}
|
|
||||||
.app-nav ul,
|
|
||||||
.app-nav li {
|
|
||||||
display: inline-block;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.app-nav a {
|
|
||||||
color: inherit;
|
|
||||||
font-size: 16px;
|
|
||||||
text-decoration: none;
|
|
||||||
-webkit-transition: color 0.3s;
|
|
||||||
transition: color 0.3s;
|
|
||||||
}
|
|
||||||
.app-nav a:hover {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
.app-nav a.active {
|
|
||||||
border-bottom: 2px solid var(--theme-color, #ea6f5a);
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
.app-nav li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 1rem;
|
|
||||||
padding: 5px 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.app-nav li ul {
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-bottom-color: #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: none;
|
|
||||||
max-height: calc(100vh - 61px);
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 10px 0;
|
|
||||||
position: absolute;
|
|
||||||
right: -15px;
|
|
||||||
text-align: left;
|
|
||||||
top: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.app-nav li ul li {
|
|
||||||
display: block;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1rem;
|
|
||||||
margin: 0;
|
|
||||||
margin: 8px 14px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.app-nav li ul a {
|
|
||||||
display: block;
|
|
||||||
font-size: inherit;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.app-nav li ul a.active {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
.app-nav li:hover ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.github-corner {
|
|
||||||
border-bottom: 0;
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
text-decoration: none;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.github-corner:hover .octo-arm {
|
|
||||||
-webkit-animation: octocat-wave 560ms ease-in-out;
|
|
||||||
animation: octocat-wave 560ms ease-in-out;
|
|
||||||
}
|
|
||||||
.github-corner svg {
|
|
||||||
color: #3f3f3f;
|
|
||||||
fill: var(--theme-color, #ea6f5a);
|
|
||||||
height: 80px;
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
main {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
main.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.anchor {
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
-webkit-transition: all 0.3s;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
.anchor span {
|
|
||||||
color: #c8c8c8;
|
|
||||||
}
|
|
||||||
.anchor:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
border-right: 1px solid rgba(0,0,0,0.07);
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 40px 0 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
-webkit-transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out, -webkit-transform 250ms ease-out;
|
|
||||||
width: 300px;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
.sidebar > h1 {
|
|
||||||
margin: 0 auto 1rem;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 300;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.sidebar > h1 a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.sidebar > h1 .app-nav {
|
|
||||||
display: block;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
.sidebar .sidebar-nav {
|
|
||||||
line-height: 2em;
|
|
||||||
padding-bottom: 40px;
|
|
||||||
}
|
|
||||||
.sidebar li.collapse .app-sub-sidebar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.sidebar ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.sidebar li > p {
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.sidebar ul,
|
|
||||||
.sidebar ul li {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
.sidebar ul li a {
|
|
||||||
border-bottom: none;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.sidebar ul li ul {
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.sidebar::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
.sidebar::-webkit-scrollbar-thumb {
|
|
||||||
background: transparent;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.sidebar:hover::-webkit-scrollbar-thumb {
|
|
||||||
background: rgba(136,136,136,0.4);
|
|
||||||
}
|
|
||||||
.sidebar:hover::-webkit-scrollbar-track {
|
|
||||||
background: rgba(136,136,136,0.1);
|
|
||||||
}
|
|
||||||
.sidebar-toggle {
|
|
||||||
background-color: transparent;
|
|
||||||
background-color: rgba(63,63,63,0.8);
|
|
||||||
border: 0;
|
|
||||||
outline: none;
|
|
||||||
padding: 10px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
text-align: center;
|
|
||||||
-webkit-transition: opacity 0.3s;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
width: 284px;
|
|
||||||
z-index: 30;
|
|
||||||
}
|
|
||||||
.sidebar-toggle .sidebar-toggle-button:hover {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
.sidebar-toggle span {
|
|
||||||
background-color: var(--theme-color, #ea6f5a);
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
width: 16px;
|
|
||||||
height: 2px;
|
|
||||||
}
|
|
||||||
body.sticky .sidebar,
|
|
||||||
body.sticky .sidebar-toggle {
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
padding-top: 60px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 300px;
|
|
||||||
-webkit-transition: left 250ms ease;
|
|
||||||
transition: left 250ms ease;
|
|
||||||
}
|
|
||||||
.markdown-section {
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 800px;
|
|
||||||
padding: 30px 15px 40px 15px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.markdown-section > * {
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: inherit;
|
|
||||||
}
|
|
||||||
.markdown-section > :first-child {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
.markdown-section hr {
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
margin: 2em 0;
|
|
||||||
}
|
|
||||||
.markdown-section iframe {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
}
|
|
||||||
.markdown-section table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
overflow: auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.markdown-section th {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 6px 13px;
|
|
||||||
}
|
|
||||||
.markdown-section td {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
padding: 6px 13px;
|
|
||||||
}
|
|
||||||
.markdown-section tr {
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
.markdown-section tr:nth-child(2n) {
|
|
||||||
background-color: #555555;
|
|
||||||
}
|
|
||||||
.markdown-section p.tip {
|
|
||||||
background-color: #555555;
|
|
||||||
border-bottom-right-radius: 2px;
|
|
||||||
border-left: 4px solid #f66;
|
|
||||||
border-top-right-radius: 2px;
|
|
||||||
margin: 2em 0;
|
|
||||||
padding: 12px 24px 12px 30px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.markdown-section p.tip:before {
|
|
||||||
background-color: #f66;
|
|
||||||
border-radius: 100%;
|
|
||||||
color: #3f3f3f;
|
|
||||||
content: '!';
|
|
||||||
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
left: -12px;
|
|
||||||
line-height: 20px;
|
|
||||||
position: absolute;
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
text-align: center;
|
|
||||||
top: 14px;
|
|
||||||
}
|
|
||||||
.markdown-section p.tip code {
|
|
||||||
background-color: #efefef;
|
|
||||||
}
|
|
||||||
.markdown-section p.tip em {
|
|
||||||
color: #c8c8c8;
|
|
||||||
}
|
|
||||||
.markdown-section p.warn {
|
|
||||||
background: rgba(234,111,90,0.1);
|
|
||||||
border-radius: 2px;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
body.close .sidebar {
|
|
||||||
-webkit-transform: translateX(-300px);
|
|
||||||
transform: translateX(-300px);
|
|
||||||
}
|
|
||||||
body.close .sidebar-toggle {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
body.close .content {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
@media print {
|
|
||||||
.github-corner,
|
|
||||||
.sidebar-toggle,
|
|
||||||
.sidebar,
|
|
||||||
.app-nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
.github-corner,
|
|
||||||
.sidebar-toggle,
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
.app-nav {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
.app-nav li ul {
|
|
||||||
top: 30px;
|
|
||||||
}
|
|
||||||
main {
|
|
||||||
height: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
left: -300px;
|
|
||||||
-webkit-transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out, -webkit-transform 250ms ease-out;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
left: 0;
|
|
||||||
max-width: 100vw;
|
|
||||||
position: static;
|
|
||||||
padding-top: 20px;
|
|
||||||
-webkit-transition: -webkit-transform 250ms ease;
|
|
||||||
transition: -webkit-transform 250ms ease;
|
|
||||||
transition: transform 250ms ease;
|
|
||||||
transition: transform 250ms ease, -webkit-transform 250ms ease;
|
|
||||||
}
|
|
||||||
.app-nav,
|
|
||||||
.github-corner {
|
|
||||||
-webkit-transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: -webkit-transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out;
|
|
||||||
transition: transform 250ms ease-out, -webkit-transform 250ms ease-out;
|
|
||||||
}
|
|
||||||
.sidebar-toggle {
|
|
||||||
background-color: transparent;
|
|
||||||
width: auto;
|
|
||||||
padding: 30px 30px 10px 10px;
|
|
||||||
}
|
|
||||||
body.close .sidebar {
|
|
||||||
-webkit-transform: translateX(300px);
|
|
||||||
transform: translateX(300px);
|
|
||||||
}
|
|
||||||
body.close .sidebar-toggle {
|
|
||||||
background-color: rgba(63,63,63,0.8);
|
|
||||||
-webkit-transition: 1s background-color;
|
|
||||||
transition: 1s background-color;
|
|
||||||
width: 284px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
body.close .content {
|
|
||||||
-webkit-transform: translateX(300px);
|
|
||||||
transform: translateX(300px);
|
|
||||||
}
|
|
||||||
body.close .app-nav,
|
|
||||||
body.close .github-corner {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.github-corner:hover .octo-arm {
|
|
||||||
-webkit-animation: none;
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
.github-corner .octo-arm {
|
|
||||||
-webkit-animation: octocat-wave 560ms ease-in-out;
|
|
||||||
animation: octocat-wave 560ms ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-webkit-keyframes octocat-wave {
|
|
||||||
0%, 100% {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
20%, 60% {
|
|
||||||
-webkit-transform: rotate(-25deg);
|
|
||||||
transform: rotate(-25deg);
|
|
||||||
}
|
|
||||||
40%, 80% {
|
|
||||||
-webkit-transform: rotate(10deg);
|
|
||||||
transform: rotate(10deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes octocat-wave {
|
|
||||||
0%, 100% {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
20%, 60% {
|
|
||||||
-webkit-transform: rotate(-25deg);
|
|
||||||
transform: rotate(-25deg);
|
|
||||||
}
|
|
||||||
40%, 80% {
|
|
||||||
-webkit-transform: rotate(10deg);
|
|
||||||
transform: rotate(10deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
section.cover {
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
background-position: center center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
height: 100vh;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
section.cover.show {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
section.cover.has-mask .mask {
|
|
||||||
background-color: #3f3f3f;
|
|
||||||
opacity: 0.8;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
section.cover .cover-main {
|
|
||||||
-webkit-box-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
margin: -20px 16px 0;
|
|
||||||
text-align: center;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
section.cover a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
section.cover a:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
section.cover p {
|
|
||||||
line-height: 1.5rem;
|
|
||||||
margin: 1em 0;
|
|
||||||
}
|
|
||||||
section.cover h1 {
|
|
||||||
color: inherit;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
font-weight: 300;
|
|
||||||
margin: 0.625rem 0 2.5rem;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
section.cover h1 a {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
section.cover h1 small {
|
|
||||||
bottom: -0.4375rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
section.cover blockquote {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
section.cover ul {
|
|
||||||
line-height: 1.8;
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 1em auto;
|
|
||||||
max-width: 500px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
section.cover .cover-main > p:last-child a {
|
|
||||||
border-color: var(--theme-color, #ea6f5a);
|
|
||||||
border-radius: 2rem;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 1.05rem;
|
|
||||||
letter-spacing: 0.1rem;
|
|
||||||
margin: 0.5rem 1rem;
|
|
||||||
padding: 0.75em 2rem;
|
|
||||||
text-decoration: none;
|
|
||||||
-webkit-transition: all 0.15s ease;
|
|
||||||
transition: all 0.15s ease;
|
|
||||||
}
|
|
||||||
section.cover .cover-main > p:last-child a:last-child {
|
|
||||||
background-color: var(--theme-color, #ea6f5a);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
section.cover .cover-main > p:last-child a:last-child:hover {
|
|
||||||
color: inherit;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
section.cover .cover-main > p:last-child a:hover {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
section.cover blockquote > p > a {
|
|
||||||
border-bottom: 2px solid var(--theme-color, #ea6f5a);
|
|
||||||
-webkit-transition: color 0.3s;
|
|
||||||
transition: color 0.3s;
|
|
||||||
}
|
|
||||||
section.cover blockquote > p > a:hover {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
background-color: #3f3f3f;
|
|
||||||
}
|
|
||||||
/* sidebar */
|
|
||||||
.sidebar {
|
|
||||||
background-color: #3f3f3f;
|
|
||||||
color: #c8c8c8;
|
|
||||||
}
|
|
||||||
.sidebar li {
|
|
||||||
margin: 6px 15px;
|
|
||||||
}
|
|
||||||
.sidebar ul li a {
|
|
||||||
color: #c8c8c8;
|
|
||||||
font-size: 14px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-decoration: none;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.sidebar ul li a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
.sidebar ul li ul {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.sidebar ul li.active > a {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
/* markdown content found on pages */
|
|
||||||
.markdown-section h1,
|
|
||||||
.markdown-section h2,
|
|
||||||
.markdown-section h3,
|
|
||||||
.markdown-section h4,
|
|
||||||
.markdown-section strong {
|
|
||||||
color: #657b83;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.markdown-section a {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.markdown-section h1 {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
.markdown-section h2 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
margin: 45px 0 0.8rem;
|
|
||||||
}
|
|
||||||
.markdown-section h3 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
margin: 40px 0 0.6rem;
|
|
||||||
}
|
|
||||||
.markdown-section h4 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
.markdown-section h5 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
.markdown-section h6 {
|
|
||||||
color: #777;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
.markdown-section figure,
|
|
||||||
.markdown-section p,
|
|
||||||
.markdown-section ul,
|
|
||||||
.markdown-section ol {
|
|
||||||
margin: 1.2em 0;
|
|
||||||
}
|
|
||||||
.markdown-section p,
|
|
||||||
.markdown-section ul,
|
|
||||||
.markdown-section ol {
|
|
||||||
line-height: 1.6rem;
|
|
||||||
word-spacing: 0.05rem;
|
|
||||||
}
|
|
||||||
.markdown-section ul,
|
|
||||||
.markdown-section ol {
|
|
||||||
padding-left: 1.5rem;
|
|
||||||
}
|
|
||||||
.markdown-section blockquote {
|
|
||||||
border-left: 4px solid var(--theme-color, #ea6f5a);
|
|
||||||
color: #858585;
|
|
||||||
margin: 2em 0;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.markdown-section blockquote p {
|
|
||||||
font-weight: 600;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
.markdown-section iframe {
|
|
||||||
margin: 1em 0;
|
|
||||||
}
|
|
||||||
.markdown-section em {
|
|
||||||
color: #7f8c8d;
|
|
||||||
}
|
|
||||||
.markdown-section code {
|
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 2px;
|
|
||||||
color: #aaaaaa;
|
|
||||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
margin: 0 2px;
|
|
||||||
padding: 3px 5px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
.markdown-section pre {
|
|
||||||
-moz-osx-font-smoothing: initial;
|
|
||||||
-webkit-font-smoothing: initial;
|
|
||||||
background-color: #282828;
|
|
||||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
margin: 1.2em 0;
|
|
||||||
overflow: auto;
|
|
||||||
padding: 0 1.4rem;
|
|
||||||
position: relative;
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
/* code highlight */
|
|
||||||
.token.comment,
|
|
||||||
.token.prolog,
|
|
||||||
.token.doctype,
|
|
||||||
.token.cdata {
|
|
||||||
color: #8e908c;
|
|
||||||
}
|
|
||||||
.token.namespace {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
.token.boolean,
|
|
||||||
.token.number {
|
|
||||||
color: #c76b29;
|
|
||||||
}
|
|
||||||
.token.punctuation {
|
|
||||||
color: #525252;
|
|
||||||
}
|
|
||||||
.token.property {
|
|
||||||
color: #c08b30;
|
|
||||||
}
|
|
||||||
.token.tag {
|
|
||||||
color: #2973b7;
|
|
||||||
}
|
|
||||||
.token.string {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
.token.selector {
|
|
||||||
color: #6679cc;
|
|
||||||
}
|
|
||||||
.token.attr-name {
|
|
||||||
color: #2973b7;
|
|
||||||
}
|
|
||||||
.token.entity,
|
|
||||||
.token.url,
|
|
||||||
.language-css .token.string,
|
|
||||||
.style .token.string {
|
|
||||||
color: #22a2c9;
|
|
||||||
}
|
|
||||||
.token.attr-value,
|
|
||||||
.token.control,
|
|
||||||
.token.directive,
|
|
||||||
.token.unit {
|
|
||||||
color: var(--theme-color, #ea6f5a);
|
|
||||||
}
|
|
||||||
.token.keyword {
|
|
||||||
color: #e96900;
|
|
||||||
}
|
|
||||||
.token.statement,
|
|
||||||
.token.regex,
|
|
||||||
.token.atrule {
|
|
||||||
color: #22a2c9;
|
|
||||||
}
|
|
||||||
.token.placeholder,
|
|
||||||
.token.variable {
|
|
||||||
color: #3d8fd1;
|
|
||||||
}
|
|
||||||
.token.deleted {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
|
||||||
.token.inserted {
|
|
||||||
border-bottom: 1px dotted #202746;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.token.italic {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
.token.important,
|
|
||||||
.token.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.token.important {
|
|
||||||
color: #c94922;
|
|
||||||
}
|
|
||||||
.token.entity {
|
|
||||||
cursor: help;
|
|
||||||
}
|
|
||||||
.markdown-section pre > code {
|
|
||||||
-moz-osx-font-smoothing: initial;
|
|
||||||
-webkit-font-smoothing: initial;
|
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 2px;
|
|
||||||
color: #657b83;
|
|
||||||
display: block;
|
|
||||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
line-height: inherit;
|
|
||||||
margin: 0 2px;
|
|
||||||
max-width: inherit;
|
|
||||||
overflow: inherit;
|
|
||||||
padding: 2.2em 5px;
|
|
||||||
white-space: inherit;
|
|
||||||
}
|
|
||||||
.markdown-section code::after,
|
|
||||||
.markdown-section code::before {
|
|
||||||
letter-spacing: 0.05rem;
|
|
||||||
}
|
|
||||||
code .token {
|
|
||||||
-moz-osx-font-smoothing: initial;
|
|
||||||
-webkit-font-smoothing: initial;
|
|
||||||
min-height: 1.5rem;
|
|
||||||
}
|
|
||||||
pre::after {
|
|
||||||
color: #ccc;
|
|
||||||
content: attr(data-lang);
|
|
||||||
font-size: 0.6rem;
|
|
||||||
font-weight: 600;
|
|
||||||
height: 15px;
|
|
||||||
line-height: 15px;
|
|
||||||
padding: 5px 10px 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
text-align: right;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.markdown-section p.tip {
|
|
||||||
background-color: #282828;
|
|
||||||
color: #657b83;
|
|
||||||
}
|
|
||||||
input[type='search'] {
|
|
||||||
background: #4f4f4f;
|
|
||||||
border-color: #4f4f4f;
|
|
||||||
color: #c8c8c8;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
# Quantum Keycodes
|
|
||||||
|
|
||||||
Quantum keycodes allow for easier customisation of your keymap than the basic ones provide, without having to define custom actions.
|
|
||||||
|
|
||||||
All keycodes within quantum are numbers between `0x0000` and `0xFFFF`. Within your `keymap.c` it may look like you have functions and other special cases, but ultimately the C preprocessor will translate those into a single 4 byte integer. QMK has reserved `0x0000` through `0x00FF` for standard keycodes. These are keycodes such as `KC_A`, `KC_1`, and `KC_LCTL`, which are basic keys defined in the USB HID specification.
|
|
||||||
|
|
||||||
On this page we have documented keycodes between `0x00FF` and `0xFFFF` which are used to implement advanced quantum features. If you define your own custom keycodes they will be put into this range as well.
|
|
||||||
|
|
||||||
## QMK Keycodes
|
|
||||||
|
|
||||||
|Key |Aliases |Description |
|
|
||||||
|---------------|-----------|---------------------------------------------------------------------|
|
|
||||||
|`RESET` | |Put the keyboard into DFU mode for flashing |
|
|
||||||
|`DEBUG` | |Toggle debug mode |
|
|
||||||
|`EEPROM_RESET` |`EEP_RST` |Resets EEPROM state by reinitializing it |
|
|
||||||
|`KC_GESC` |`GRAVE_ESC`|Escape when tapped, <code>`</code> when pressed with Shift or GUI|
|
|
||||||
|`KC_LSPO` | |Left Shift when held, `(` when tapped |
|
|
||||||
|`KC_RSPC` | |Right Shift when held, `)` when tapped |
|
|
||||||
|`KC_LEAD` | |The [Leader key](feature_leader_key.md) |
|
|
||||||
|`KC_LOCK` | |The [Lock key](feature_key_lock.md) |
|
|
||||||
|`FUNC(n)` |`F(n)` |Call `fn_action(n)` (deprecated) |
|
|
||||||
|`M(n)` | |Call macro `n` |
|
|
||||||
|`MACROTAP(n)` | |Macro-tap `n` idk FIXME |
|
|
@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"redirects": [
|
|
||||||
{
|
|
||||||
"from": "adding_a_keyboard_to_qmk.html",
|
|
||||||
"to": "hardware_keyboard_guidelines.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "build_environment_setup.html",
|
|
||||||
"to": "getting_started_build_tools.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "dynamic_macros.html",
|
|
||||||
"to": "feature_dynamic_macros.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "feature_common_shortcuts.html",
|
|
||||||
"to": "feature_advanced_keycodes.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "glossary.html",
|
|
||||||
"to": "reference_glossary.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "key_lock.html",
|
|
||||||
"to": "feature_key_lock.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "make_instructions.html",
|
|
||||||
"to": "getting_started_make_guide.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "porting_your_keyboard_to_qmk.html",
|
|
||||||
"to": "hardware_avr.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "space_cadet_shift.html",
|
|
||||||
"to": "feature_space_cadet_shift.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "tap_dance.html",
|
|
||||||
"to": "feature_tap_dance.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": "unicode.html",
|
|
||||||
"to": "feature_unicode.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,195 +0,0 @@
|
|||||||
# Supporting Your Keyboard in QMK Configurator
|
|
||||||
|
|
||||||
This page covers how to properly support keyboards in the [QMK Configurator](https://config.qmk.fm/).
|
|
||||||
|
|
||||||
|
|
||||||
## How the Configurator Understands Keyboards
|
|
||||||
|
|
||||||
To understand how the Configurator understands keyboards, first one must understand layout macros. For this exercise, we're going to imagine a 17-key numpad PCB, which we're going to call `numpad`.
|
|
||||||
|
|
||||||
```
|
|
||||||
┌───┬───┬───┬───┐
|
|
||||||
│NLk│ / │ * │ - │
|
|
||||||
├───┼───┼───┼───┤
|
|
||||||
│7 │8 │9 │ + │
|
|
||||||
├───┼───┼───┤ │
|
|
||||||
│4 │5 │6 │ │
|
|
||||||
├───┼───┼───┼───┤
|
|
||||||
│1 │2 │3 │Ent│
|
|
||||||
├───┴───┼───┤ │
|
|
||||||
│0 │ . │ │
|
|
||||||
└───────┴───┴───┘
|
|
||||||
```
|
|
||||||
|
|
||||||
?> For more on layout macros, see [Understanding QMK: Matrix Scanning](understanding_qmk.md?id=matrix-scanning) and [Understanding QMK: Matrix to Physical Layout Map](understanding_qmk.md?id=matrix-to-physical-layout-map).
|
|
||||||
|
|
||||||
The Configurator's API reads the keyboard's `.h` file from `qmk_firmware/keyboards/<keyboard>/<keyboard>.h`. For our numpad, this file would be `qmk_firmware/keyboards/numpad/numpad.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define LAYOUT( \
|
|
||||||
k00, k01, k02, k03, \
|
|
||||||
k10, k11, k12, k13, \
|
|
||||||
k20, k21, k22, \
|
|
||||||
k30, k31, k32, k33, \
|
|
||||||
k40, k42 \
|
|
||||||
) { \
|
|
||||||
{ k00, k01, k02, k03 }, \
|
|
||||||
{ k10, k11, k12, k13 }, \
|
|
||||||
{ k20, k21, k22, KC_NO }, \
|
|
||||||
{ k30, k31, k32, k33 }, \
|
|
||||||
{ k40, KC_NO, k42, KC_NO } \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
QMK uses `KC_NO` to designate places in the switch matrix where there is no switch. Sometimes, `XXX`, `___` or `____` are used as shorthand to make this section easier to read if it needs to be debugged. This is usually defined near the beginning of the `.h` file:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define XXX KC_NO
|
|
||||||
|
|
||||||
#define LAYOUT( \
|
|
||||||
k00, k01, k02, k03, \
|
|
||||||
k10, k11, k12, k13, \
|
|
||||||
k20, k21, k22, \
|
|
||||||
k30, k31, k32, k33, \
|
|
||||||
k40, k42 \
|
|
||||||
) { \
|
|
||||||
{ k00, k01, k02, k03 }, \
|
|
||||||
{ k10, k11, k12, k13 }, \
|
|
||||||
{ k20, k21, k22, XXX }, \
|
|
||||||
{ k30, k31, k32, k33 }, \
|
|
||||||
{ k40, XXX, k42, XXX } \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
!> This usage differs from that of keymap macros, which almost always use `XXXXXXX` (seven capital X's) for `KC_NO` and `_______` (seven underscores) for `KC_TRNS`.
|
|
||||||
|
|
||||||
!> To prevent user confusion, using `KC_NO` is preferred.
|
|
||||||
|
|
||||||
The layout macro tells the Configurator that our keyboard has 17 keys, arranged in five rows of four columns each. Our switch positions are named `k<row><column>`, counting from 0. The names themselves actually don't matter, as long as they match between the top section, which receives the keycodes from the keymap, and the bottom half which designates where each key is in the matrix.
|
|
||||||
|
|
||||||
To display our keyboard in a way that resembles the physical keyboard, we need to build a JSON file that tells the Configurator how to tie the physical locations and sizes of our keys to our switch matrix.
|
|
||||||
|
|
||||||
## Building the JSON file
|
|
||||||
|
|
||||||
To build the JSON file, the easiest way is to build the layout in [Keyboard Layout Editor](http://www.keyboard-layout-editor.com/) ("KLE"), from which we'll feed the Raw Data into a QMK tool that converts this data into a JSON the Configurator will read and use. Since KLE opens by default with a numpad layout, we're just going to remove the Getting Started instructions, and use what's left.
|
|
||||||
|
|
||||||
Once the layout is as desired, move to the Raw Data tab in KLE, and copy the contents:
|
|
||||||
|
|
||||||
```
|
|
||||||
["Num Lock","/","*","-"],
|
|
||||||
["7\nHome","8\n↑","9\nPgUp",{h:2},"+"],
|
|
||||||
["4\n←","5","6\n→"],
|
|
||||||
["1\nEnd","2\n↓","3\nPgDn",{h:2},"Enter"],
|
|
||||||
[{w:2},"0\nIns",".\nDel"]
|
|
||||||
```
|
|
||||||
|
|
||||||
To convert this data into our JSON, go to the [QMK KLE-JSON Converter](https://qmk.fm/converter/), paste the Raw Data into the Input field, and click the Convert button. After a moment, our JSON data will appear in the Output field. Copy the contents to a new text document, and name the document `info.json`, saving it in the same folder that contains `numpad.h`.
|
|
||||||
|
|
||||||
Use the `keyboard_name` object to set the name of the keyboard. The `bootloader` object is deprecated, so it can be deleted. For instruction purposes, we will put each key's object on its own line. This is only to make the file more human-readable, and does not affect the Configurator's functionality.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"keyboard_name": "Numpad",
|
|
||||||
"url": "",
|
|
||||||
"maintainer": "qmk",
|
|
||||||
"tags": {
|
|
||||||
"form_factor": "numpad"
|
|
||||||
},
|
|
||||||
"width": 4,
|
|
||||||
"height": 5,
|
|
||||||
"layouts": {
|
|
||||||
"LAYOUT": {
|
|
||||||
"layout": [
|
|
||||||
{"label":"Num Lock", "x":0, "y":0},
|
|
||||||
{"label":"/", "x":1, "y":0},
|
|
||||||
{"label":"*", "x":2, "y":0},
|
|
||||||
{"label":"-", "x":3, "y":0},
|
|
||||||
{"label":"7", "x":0, "y":1},
|
|
||||||
{"label":"8", "x":1, "y":1},
|
|
||||||
{"label":"9", "x":2, "y":1},
|
|
||||||
{"label":"+", "x":3, "y":1, "h":2},
|
|
||||||
{"label":"4", "x":0, "y":2},
|
|
||||||
{"label":"5", "x":1, "y":2},
|
|
||||||
{"label":"6", "x":2, "y":2},
|
|
||||||
{"label":"1", "x":0, "y":3},
|
|
||||||
{"label":"2", "x":1, "y":3},
|
|
||||||
{"label":"3", "x":2, "y":3},
|
|
||||||
{"label":"Enter", "x":3, "y":3, "h":2},
|
|
||||||
{"label":"0", "x":0, "y":4, "w":2},
|
|
||||||
{"label":".", "x":2, "y":4}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `layouts` object contains the data that represents the physical layout of the keyboard. It has an object `LAYOUT`, which needs to match the name of our layout macro from `numpad.h`. The `LAYOUT` object itself has an object named `layout`, which contains one JSON object for each physical key on our keyboard, formatted as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
┌ The name of the key. Not displayed in the Configurator.
|
|
||||||
│ ┌ The key's X-axis location, in key units from the
|
|
||||||
│ │ keyboard's left edge.
|
|
||||||
│ │ ┌ The key's Y-axis location, in key units from
|
|
||||||
│ │ │ the keyboard's top (rear-facing) edge.
|
|
||||||
↓ ↓ ↓
|
|
||||||
{"label":"Num Lock", "x":0, "y":0},
|
|
||||||
```
|
|
||||||
|
|
||||||
Some objects will also have `"w"` and `"h"` keys, which represent a key's width and height, respectively.
|
|
||||||
|
|
||||||
?> For more on the `info.json` files, see [QMK Keyboard Guidelines: Keyboard Metadata](hardware_keyboard_guidelines.md?id=keyboard-metadata)
|
|
||||||
|
|
||||||
|
|
||||||
## How the Configurator Programs Keys
|
|
||||||
|
|
||||||
The Configurator's API uses the layout macro and the JSON file we've given it to create a visual representation of the keyboard that has each visual object tied to a specific key, in sequence:
|
|
||||||
|
|
||||||
key in layout macro | JSON object used
|
|
||||||
:---: | :----
|
|
||||||
k00 | {"label":"Num Lock", "x":0, "y":0}
|
|
||||||
k01 | {"label":"/", "x":1, "y":0}
|
|
||||||
k02 | {"label":"*", "x":2, "y":0}
|
|
||||||
k03 | {"label":"-", "x":3, "y":0}
|
|
||||||
k10 | {"label":"7", "x":0, "y":1}
|
|
||||||
k11 | {"label":"8", "x":1, "y":1}
|
|
||||||
k12 | {"label":"9", "x":2, "y":1}
|
|
||||||
k13 | {"label":"+", "x":3, "y":1, "h":2}
|
|
||||||
k20 | {"label":"4", "x":0, "y":2}
|
|
||||||
k21 | {"label":"5", "x":1, "y":2}
|
|
||||||
k22 | {"label":"6", "x":2, "y":2}
|
|
||||||
k30 | {"label":"1", "x":0, "y":3}
|
|
||||||
k31 | {"label":"2", "x":1, "y":3}
|
|
||||||
k32 | {"label":"3", "x":2, "y":3}
|
|
||||||
k33 | {"label":"Enter", "x":3, "y":3, "h":2}
|
|
||||||
k40 | {"label":"0", "x":0, "y":4, "w":2}
|
|
||||||
k42 | {"label":".", "x":2, "y":4}
|
|
||||||
|
|
||||||
When a user selects the top-left key in the Configurator, and assigns Num Lock to it, the Configurator builds a keymap file with `KC_NLCK` as the first key, and so on as the keymap is built. The `label` keys are not used; they are only for the user's reference in identifying specific keys when debugging the `info.json` file.
|
|
||||||
|
|
||||||
|
|
||||||
## Issues and Hazards
|
|
||||||
|
|
||||||
Currently, the Configurator does not support key rotation or non-rectangular key shapes like ISO Enter. Additionally, keys that are vertically-offset from their "row" — the arrow keys on 1800-layouts like the [TKC1800](https://github.com/qmk/qmk_firmware/tree/4ac48a61a66206beaf2fdd5f2939d8bbedd0004c/keyboards/tkc1800/) being a prominent example — confuse the KLE-to-JSON Converter, if not adjusted for by the contributor of the `info.json` file.
|
|
||||||
|
|
||||||
### Workarounds
|
|
||||||
|
|
||||||
#### Non-rectangular keys
|
|
||||||
|
|
||||||
For ISO Enter keys, QMK custom is to display it as a rectangular key, 1.25u wide and 2u high, aligned so its right edge is aligned with the right edge of the alphanumeric key block.
|
|
||||||
|
|
||||||
![](https://i.imgur.com/JKngtTw.png)
|
|
||||||
*A 60% keyboard in standard ISO layout, as rendered by QMK Configurator.*
|
|
||||||
|
|
||||||
#### Vertically-offset keys
|
|
||||||
|
|
||||||
For vertically-offset keys, place them in KLE as if they were not offset, then edit the Y-values as needed in the converted JSON file
|
|
||||||
|
|
||||||
![](https://i.imgur.com/fmDvDzR.png)
|
|
||||||
*An 1800-layout keyboard as rendered in Keyboard Layout Editor, without the vertical offset applied to the arrow keys.*
|
|
||||||
|
|
||||||
![](https://i.imgur.com/8beYMBR.png)
|
|
||||||
*A Unix diff file, showing the changes needed to vertically-offset the arrow keys in our keyboard's JSON file.*
|
|
@ -1,170 +0,0 @@
|
|||||||
# Glossary of QMK Terms
|
|
||||||
|
|
||||||
## ARM
|
|
||||||
A line of 32-bit MCU's produced by a number of companies, such as Atmel, Cypress, Kinetis, NXP, ST, and TI.
|
|
||||||
|
|
||||||
## AVR
|
|
||||||
A line of 8-bit MCU's produced by [Atmel](http://www.microchip.com/). AVR was the original platform that TMK supported.
|
|
||||||
|
|
||||||
## AZERTY
|
|
||||||
The standard Français (French) keyboard layout. Named for the first 6 keys on the keyboard.
|
|
||||||
|
|
||||||
## Backlight
|
|
||||||
A generic term for lighting on a keyboard. The backlight is typically, but not always, an array of LED's that shine through keycaps and/or switches.
|
|
||||||
|
|
||||||
## Bluetooth
|
|
||||||
A short range peer to peer wireless protocol. Most common wireless protocol for a keyboard.
|
|
||||||
|
|
||||||
## Bootloader
|
|
||||||
A special program that is written to a protected area of your MCU that allows the MCU to upgrade its own firmware, typically over USB.
|
|
||||||
|
|
||||||
## Bootmagic
|
|
||||||
A feature that allows for various keyboard behavior changes to happen on the fly, such as swapping or disabling common keys.
|
|
||||||
|
|
||||||
## C
|
|
||||||
A low-level programming language suitable for system code. Most QMK code is written in C.
|
|
||||||
|
|
||||||
## Colemak
|
|
||||||
An alternative keyboard layout that is gaining in popularity.
|
|
||||||
|
|
||||||
## Compile
|
|
||||||
The process of turning human readable code into machine code your MCU can run.
|
|
||||||
|
|
||||||
## Dvorak
|
|
||||||
An alternative keyboard layout developed by Dr. August Dvorak in the 1930's. A shortened form of the Dvorak Simplified Keyboard.
|
|
||||||
|
|
||||||
## Dynamic Macro
|
|
||||||
A macro which has been recorded on the keyboard and which will be lost when the keyboard is unplugged or the computer rebooted.
|
|
||||||
|
|
||||||
* [Dynamic Macro Documentation](feature_dynamic_macros.md)
|
|
||||||
|
|
||||||
## Eclipse
|
|
||||||
An IDE that is popular with many C developers.
|
|
||||||
|
|
||||||
* [Eclipse Setup Instructions](eclipse.md)
|
|
||||||
|
|
||||||
## Firmware
|
|
||||||
The software that controls your MCU.
|
|
||||||
|
|
||||||
## FLIP
|
|
||||||
Software provided by Atmel for flashing AVR devices. We generally recommend [QMK Flasher](https://github.com/qmk/qmk_flasher) instead, but for some advanced use cases FLIP is required.
|
|
||||||
|
|
||||||
## git
|
|
||||||
Versioning software used at the command line
|
|
||||||
|
|
||||||
## GitHub
|
|
||||||
The website that hosts most of the QMK project. It provides integration with git, issue tracking, and other features that help us run QMK.
|
|
||||||
|
|
||||||
## ISP
|
|
||||||
In-system programming, a method of programming an AVR chip using external hardware and the JTAG pins.
|
|
||||||
|
|
||||||
## hid_listen
|
|
||||||
An interface for receiving debugging messages from your keyboard. You can view these messages using [QMK Flasher](https://github.com/qmk/qmk_flasher) or [PJRC's hid_listen](https://www.pjrc.com/teensy/hid_listen.html)
|
|
||||||
|
|
||||||
## Keycode
|
|
||||||
A 2-byte number that represents a particular key. `0x00`-`0xFF` are used for [Basic Keycodes](keycodes_basic.md) while `0x100`-`0xFFFF` are used for [Quantum Keycodes](quantum_keycodes.md).
|
|
||||||
|
|
||||||
## Key Down
|
|
||||||
An event that happens when a key is pressed down, but is completed before a key is released.
|
|
||||||
|
|
||||||
## Key Up
|
|
||||||
An event that happens when a key is released.
|
|
||||||
|
|
||||||
## Keymap
|
|
||||||
An array of keycodes mapped to a physical keyboard layout, which are processed on key presses and releases
|
|
||||||
|
|
||||||
## Layer
|
|
||||||
An abstraction used to allow a key to serve multiple purposes. The highest active layer takes precedence.
|
|
||||||
|
|
||||||
## Leader Key
|
|
||||||
A feature that allows you to tap the leader key followed by a sequence of 1, 2, or 3 keys to activate key presses or other quantum features.
|
|
||||||
|
|
||||||
* [Leader Key Documentation](feature_leader_key.md)
|
|
||||||
|
|
||||||
## LED
|
|
||||||
Light Emitting Diode, the most common device used for indicators on a keyboard.
|
|
||||||
|
|
||||||
## Make
|
|
||||||
Software package that is used to compile all the source files. You run `make` with various options to compile your keyboard firmware.
|
|
||||||
|
|
||||||
## Matrix
|
|
||||||
A wiring pattern of columns and rows that enables the MCU to detect keypresses with a fewer number of pins. The matrix often incorporates diodes to allow for NKRO.
|
|
||||||
|
|
||||||
## Macro
|
|
||||||
A feature that lets you send multiple keypress events (hid reports) after having pressed only a single key.
|
|
||||||
|
|
||||||
* [Macro Documentation](feature_macros.md)
|
|
||||||
|
|
||||||
## MCU
|
|
||||||
Microcontrol Unit, the processor that powers your keyboard.
|
|
||||||
|
|
||||||
## Modifier
|
|
||||||
A key that is held down while typing another key to modify the action of that key. Examples include Ctrl, Alt, and Shift.
|
|
||||||
|
|
||||||
## Mousekeys
|
|
||||||
A feature that lets you control your mouse cursor and click from your keyboard.
|
|
||||||
|
|
||||||
* [Mousekeys Documentation](feature_mouse_keys.md)
|
|
||||||
|
|
||||||
## N-Key Rollover (NKRO)
|
|
||||||
A term that applies to keyboards that are capable of reporting any number of key-presses at once.
|
|
||||||
|
|
||||||
## Oneshot Modifier
|
|
||||||
A modifier that acts as if it is held down until another key is released, so you can press the mod and then press the key, rather than holding the mod while pressing the key. Also known as a Sticky key or a Dead key.
|
|
||||||
|
|
||||||
## ProMicro
|
|
||||||
A low cost AVR development board. Clones of this device are often found on ebay very inexpensively (under $5) but people often struggle with flashing their pro micros.
|
|
||||||
|
|
||||||
## Pull Request
|
|
||||||
A request to submit code to QMK. We encourage all users to submit Pull Requests for their personal keymaps.
|
|
||||||
|
|
||||||
## QWERTY
|
|
||||||
The standard English keyboard layout, and often a shortcut for other language's standard layouts. Named for the first 6 letters on the keyboard.
|
|
||||||
|
|
||||||
## QWERTZ
|
|
||||||
The standard Deutsche (German) keyboard layout. Named for the first 6 letters on the keyboard.
|
|
||||||
|
|
||||||
## Rollover
|
|
||||||
The term for pressing a key while a key is already held down. Variants include 2KRO, 6KRO, and NKRO.
|
|
||||||
|
|
||||||
## Scancode
|
|
||||||
A 1 byte number that is sent as part of a HID report over USB that represents a single key. These numbers are documented in the [HID Usage Tables](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf) published by the [USB-IF](http://www.usb.org/).
|
|
||||||
|
|
||||||
## Space Cadet Shift
|
|
||||||
A special set of shift keys which allow you to type various types of braces by tapping the left or right shift one or more times.
|
|
||||||
|
|
||||||
* [Space Cadet Shift Documentation](feature_space_cadet_shift.md)
|
|
||||||
|
|
||||||
## Tap
|
|
||||||
Pressing and releasing a key. In some situations you will need to distinguish between a key down and a key up event, and Tap always refers to both at once.
|
|
||||||
|
|
||||||
## Tap Dance
|
|
||||||
A feature that lets you assign multiple keycodes to the same key based on how many times you press it.
|
|
||||||
|
|
||||||
* [Tap Dance Documentation](feature_tap_dance.md)
|
|
||||||
|
|
||||||
## Teensy
|
|
||||||
A low-cost AVR development board that is commonly used for hand-wired builds. A teensy is often chosen despite costing a few dollars more due to its halfkay bootloader, which makes flashing very simple.
|
|
||||||
|
|
||||||
## Underlight
|
|
||||||
A generic term for LEDs that light the underside of the board. These LED's typically shine away from the bottom of the PCB and towards the surface the keyboard rests on.
|
|
||||||
|
|
||||||
## Unicode
|
|
||||||
In the larger computer world Unicode is a set of encoding schemes for representing characters in any language. As it relates to QMK it means using various OS schemes to send unicode codepoints instead of scancodes.
|
|
||||||
|
|
||||||
* [Unicode Documentation](feature_unicode.md)
|
|
||||||
|
|
||||||
## Unit Testing
|
|
||||||
A framework for running automated tests against QMK. Unit testing helps us be confident that our changes do not break anything.
|
|
||||||
|
|
||||||
* [Unit Testing Documentation](unit_testing.md)
|
|
||||||
|
|
||||||
## USB
|
|
||||||
Universal Serial Bus, the most common wired interface for a keyboard.
|
|
||||||
|
|
||||||
## USB Host (or simply Host)
|
|
||||||
The USB Host is your computer, or whatever device your keyboard is plugged into.
|
|
||||||
|
|
||||||
# Couldn't Find the Term You're Looking For?
|
|
||||||
|
|
||||||
[Open an issue](https://github.com/qmk/qmk_firmware/issues) with your question and the term in question could be added here. Better still, open a pull request with the definition. :)
|
|
@ -1,73 +0,0 @@
|
|||||||
# `info.json`
|
|
||||||
|
|
||||||
This file is used by the [QMK API](https://github.com/qmk/qmk_api). It contains the information [QMK Configurator](https://config.qmk.fm/) needs to display a representation of your keyboard. You can also set metadata here.
|
|
||||||
|
|
||||||
You can create `info.json` files at every level under `qmk_firmware/keyboards/<name>` to specify this metadata. These files are combined, with more specific files overriding keys in less specific files. This means you do not need to duplicate your metadata information. For example, `qmk_firmware/keyboards/clueboard/info.json` specifies `manufacturer` and `maintainer`, while `qmk_firmware/keyboards/clueboard/66/info.json` specifies more specific information about Clueboard 66%.
|
|
||||||
|
|
||||||
## `info.json` Format
|
|
||||||
|
|
||||||
The `info.json` file is a JSON formatted dictionary with the following keys available to be set. You do not have to set all of them, merely the keys that apply to your keyboard.
|
|
||||||
|
|
||||||
* `keyboard_name`
|
|
||||||
* A free-form text string describing the keyboard.
|
|
||||||
* Example: `Clueboard 66%`
|
|
||||||
* `url`
|
|
||||||
* A URL to the keyboard's product page, [QMK.fm/keyboards](https://qmk.fm/keyboards) page, or other page describing information about the keyboard.
|
|
||||||
* `maintainer`
|
|
||||||
* GitHub username of the maintainer, or `qmk` for community maintained boards
|
|
||||||
* `width`
|
|
||||||
* Width of the board in Key Units
|
|
||||||
* `height`
|
|
||||||
* Height of the board in Key Units
|
|
||||||
* `layouts`
|
|
||||||
* Physical Layout representations. See the next section for more detail.
|
|
||||||
|
|
||||||
### Layout Format
|
|
||||||
|
|
||||||
Within our `info.json` file the `layouts` portion of the dictionary contains several nested dictionaries. The outer layer consists of QMK layout macros, for example `LAYOUT_ansi` or `LAYOUT_iso`. Within each layout macro are keys for `width`, `height`, and `key_count`, each of which should be self-explanatory.
|
|
||||||
|
|
||||||
* `width`
|
|
||||||
* Optional: The width of the layout in Key Units
|
|
||||||
* `height`
|
|
||||||
* Optional: The height of the layout in Key Units
|
|
||||||
* `key_count`
|
|
||||||
* **Required**: The number of keys in this layout
|
|
||||||
* `layout`
|
|
||||||
* A list of Key Dictionaries describing the physical layout. See the next section for more details.
|
|
||||||
|
|
||||||
### Key Dictionary Format
|
|
||||||
|
|
||||||
Each Key Dictionary in a layout describes the physical properties of a key. If you are familiar with the Raw Code for <http://keyboard-layout-editor.com> you will find many of the concepts the same. We re-use the same key names and layout choices wherever possible, but unlike keyboard-layout-editor each key is stateless, inheriting no properties from the keys that came before it.
|
|
||||||
|
|
||||||
All key positions and rotations are specified in relation to the top-left corner of the keyboard, and the top-left corner of each key.
|
|
||||||
|
|
||||||
* `x`
|
|
||||||
* **Required**: The absolute position of the key in the horizontal axis, in Key Units.
|
|
||||||
* `y`
|
|
||||||
* **Required**: The absolute position of the key in the vertical axis, in Key Units.
|
|
||||||
* `w`
|
|
||||||
* The width of the key, in Key Units. Ignored if `ks` is provided. Default: `1`
|
|
||||||
* `h`
|
|
||||||
* The height of the key, in Key Units. Ignored if `ks` is provided. Default: `1`
|
|
||||||
* `r`
|
|
||||||
* How many degrees clockwise to rotate the key.
|
|
||||||
* `rx`
|
|
||||||
* The absolute position of the point to rotate the key around in the horizontal axis. Default: `x`
|
|
||||||
* `ry`
|
|
||||||
* The absolute position of the point to rotate the key around in the vertical axis. Default: `y`
|
|
||||||
* `ks`
|
|
||||||
* Key Shape: define a polygon by providing a list of points, in Key Units.
|
|
||||||
* **Important**: These are relative to the top-left of the key, not absolute.
|
|
||||||
* Example ISO Enter: `[ [0,0], [1.5,0], [1.5,2], [0.25,2], [0.25,1], [0,1], [0,0] ]`
|
|
||||||
* `label`
|
|
||||||
* What to name this position in the matrix.
|
|
||||||
* This should usually be the same name as what is silkscreened on the PCB at this location.
|
|
||||||
|
|
||||||
## How is the Metadata Exposed?
|
|
||||||
|
|
||||||
This metadata is primarily used in two ways:
|
|
||||||
|
|
||||||
* To allow web-based configurators to dynamically generate UI
|
|
||||||
* To support the new `make keyboard:keymap:qmk` target, which bundles this metadata up with the firmware to allow QMK Toolbox to be smarter.
|
|
||||||
|
|
||||||
Configurator authors can see the [QMK Compiler](https://docs.api.qmk.fm/using-the-api) docs for more information on using the JSON API.
|
|
@ -1,10 +0,0 @@
|
|||||||
.sidebar-toggle {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: auto;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
# Support
|
|
||||||
|
|
||||||
If you need help with something, the best place to get quick support is going to be on our [Discord Server](https://discord.gg/Uq7gcHh). There is usually somebody online, and there are a bunch of very helpful people there.
|
|
||||||
|
|
||||||
Don't forget to read our [Code of Conduct](https://qmk.fm/coc/).
|
|
||||||
|
|
||||||
## Help! I don't know where to start!
|
|
||||||
|
|
||||||
If this is the case, then you should start with our [Newbs Guide](https://docs.qmk.fm/#/newbs). 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.
|
|
||||||
|
|
||||||
## Help! I'm having issues flashing!
|
|
||||||
|
|
||||||
First, head to the [Compiling/Flashing FAQ Page](https://docs.qmk.fm/#/faq_build). There is a good deal of info there, and you'll find a bunch of solutions to common issues there.
|
|
||||||
|
|
||||||
## Help, I have an issue that isn't covered by the links above
|
|
||||||
|
|
||||||
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](https://docs.qmk.fm/#/newbs_best_practices) 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](https://docs.qmk.fm/#/newbs_learn_more_resources).
|
|
||||||
|
|
||||||
## 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).
|
|
@ -1,182 +0,0 @@
|
|||||||
# Understanding QMK's Code
|
|
||||||
|
|
||||||
This document attempts to explain how the QMK firmware works from a very high level. It assumes you understand basic programming concepts but does not (except where needed to demonstrate) assume familiarity with C. It assumes that you have a basic understanding of the following documents:
|
|
||||||
|
|
||||||
* [Introduction](getting_started_introduction.md)
|
|
||||||
* [How Keyboards Work](how_keyboards_work.md)
|
|
||||||
* [FAQ](faq.md)
|
|
||||||
|
|
||||||
## Startup
|
|
||||||
|
|
||||||
You can think of QMK as no different from any other computer program. It is started, performs its tasks, and then ends. The entry point for the program is the `main()` function, just like it is on any other C program. However, for a newcomer to QMK it can be confusing because the `main()` function appears in multiple places, and it can be hard to tell which one to look at.
|
|
||||||
|
|
||||||
The reason for this is the different platforms that QMK supports. The most common platform is `lufa`, which runs on AVR processors such at the atmega32u4. We also support `chibios` and `vusb`.
|
|
||||||
|
|
||||||
We'll focus on AVR processors for the moment, which use the `lufa` platform. You can find the `main()` function in [tmk_core/protocol/lufa/lufa.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/protocol/lufa/lufa.c#L1028). If you browse through that function you'll find that it initializes any hardware that has been configured (including USB to the host) and then it starts the core part of the program with a [`while(1)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/protocol/lufa/lufa.c#L1069). This is [The Main Loop](#the-main-loop).
|
|
||||||
|
|
||||||
## The Main Loop
|
|
||||||
|
|
||||||
This section of code is called "The Main Loop" because it's responsible for looping over the same set of instructions forever. This is where QMK dispatches out to the functions responsible for making the keyboard do everything it is supposed to do. At first glance it can look like a lot of functionality but most of the time the code will be disabled by `#define`'s.
|
|
||||||
|
|
||||||
```
|
|
||||||
keyboard_task();
|
|
||||||
```
|
|
||||||
|
|
||||||
This is where all the keyboard specific functionality is dispatched. The source code for `keyboard_task()` can be found in [tmk_core/common/keyboard.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/keyboard.c#L216), and it is responsible for detecting changes in the matrix and turning status LED's on and off.
|
|
||||||
|
|
||||||
Within `keyboard_task()` you'll find code to handle:
|
|
||||||
|
|
||||||
* [Matrix Scanning](#matrix-scanning)
|
|
||||||
* Mouse Handling
|
|
||||||
* Serial Link(s)
|
|
||||||
* Visualizer
|
|
||||||
* Keyboard status LED's (Caps Lock, Num Lock, Scroll Lock)
|
|
||||||
|
|
||||||
#### Matrix Scanning
|
|
||||||
|
|
||||||
Matrix scanning is the core function of a keyboard firmware. It is the process of detecting which keys are currently pressed, and your keyboard runs this function many times a second. It's no exaggeration to say that 99% of your firmware's CPU time is spent on matrix scanning.
|
|
||||||
|
|
||||||
While there are different strategies for doing the actual matrix detection, they are out of scope for this document. It is sufficient to treat matrix scanning as a black box, you ask for the matrix's current state and get back a datastructure that looks like this:
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
That datastructure is a direct representation of the matrix for a 4 row by 5 column numpad. When a key is pressed that key's position within the matrix will be returned as `1` instead of `0`.
|
|
||||||
|
|
||||||
Matrix Scanning runs many times per second. The exact rate varies but typically it runs at least 10 times per second to avoid perceptible lag.
|
|
||||||
|
|
||||||
##### Matrix to Physical Layout Map
|
|
||||||
|
|
||||||
Once we know the state of every switch on our keyboard we have to map that to a keycode. In QMK this is done by making use of C macros to allow us to separate the definition of the physical layout from the definition of keycodes.
|
|
||||||
|
|
||||||
At the keyboard level we define a C macro (typically named `LAYOUT()`) which maps our keyboard's matrix to physical keys. Sometimes the matrix does not have a switch in every location, and we can use this macro to pre-populate those with KC_NO, making the keymap definition easier to work with. Here's an example `LAYOUT()` macro for a numpad:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define LAYOUT( \
|
|
||||||
k00, k01, k02, k03, \
|
|
||||||
k10, k11, k12, k13, \
|
|
||||||
k20, k21, k22, \
|
|
||||||
k30, k31, k32, k33, \
|
|
||||||
k40, k42 \
|
|
||||||
) { \
|
|
||||||
{ k00, k01, k02, k03, }, \
|
|
||||||
{ k10, k11, k12, k13, }, \
|
|
||||||
{ k20, k21, k22, KC_NO, }, \
|
|
||||||
{ k30, k31, k32, k33, }, \
|
|
||||||
{ k40, KC_NO, k42, KC_NO } \
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice how the second block of our `LAYOUT()` macro matches the Matrix Scanning array above? This macro is what will map the matrix scanning array to keycodes. However, if you look at a 17 key numpad you'll notice that it has 3 places where the matrix could have a switch but doesn't, due to larger keys. We have populated those spaces with `KC_NO` so that our keymap definition doesn't have to.
|
|
||||||
|
|
||||||
You can also use this macro to handle unusual matrix layouts, for example the [Clueboard rev 2](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/66/rev2/rev2.h). Explaining that is outside the scope of this document.
|
|
||||||
|
|
||||||
##### Keycode Assignment
|
|
||||||
|
|
||||||
At the keymap level we make use of our `LAYOUT()` macro above to map keycodes to physical locations to matrix locations. It looks like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
||||||
[0] = LAYOUT(
|
|
||||||
KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
|
|
||||||
KC_P7, KC_P8, KC_P9, KC_PPLS, \
|
|
||||||
KC_P4, KC_P5, KC_P6, \
|
|
||||||
KC_P1, KC_P2, KC_P3, KC_PENT, \
|
|
||||||
KC_P0, KC_PDOT)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice how all of these arguments match up with the first half of the `LAYOUT()` macro from the last section? This is how we take a keycode and map it to our Matrix Scan from earlier.
|
|
||||||
|
|
||||||
##### State Change Detection
|
|
||||||
|
|
||||||
The matrix scanning described above tells us the state of the matrix at a given moment, but your computer only wants to know about changes, it doesn't care about the current state. QMK stores the results from the last matrix scan and compares the results from this matrix to determine when a key has been pressed or released.
|
|
||||||
|
|
||||||
Let's look at an example. We'll hop into the middle of a keyboard scanning loop to find that our previous scan looks like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
And when our current scan completes it will look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
{1,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0},
|
|
||||||
{0,0,0,0}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Comparing against our keymap we can see that the pressed key is KC_NLCK. From here we dispatch to the `process_record` set of functions.
|
|
||||||
|
|
||||||
<!-- FIXME: Magic happens between here and process_record -->
|
|
||||||
|
|
||||||
##### Process Record
|
|
||||||
|
|
||||||
The `process_record()` function itself is deceptively simple, but hidden within is a gateway to overriding functionality at various levels of QMK. The chain of events is listed below, using cluecard whenever we need to look at the keyboard/keymap level functions. Depending on options set in `rules.mk` or elsewhere, only a subset of the functions below will be included in final firmware.
|
|
||||||
|
|
||||||
* [`void process_record(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/action.c#L172)
|
|
||||||
* [`bool process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L206)
|
|
||||||
* [Map this record to a keycode](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L226)
|
|
||||||
* [`void velocikey_accelerate(void)`](https://github.com/qmk/qmk_firmware/blob/c1c5922aae7b60b7c7d13d3769350eed9dda17ab/quantum/velocikey.c#L27)
|
|
||||||
* [`void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L119)
|
|
||||||
* [`bool process_key_lock(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_key_lock.c#L62)
|
|
||||||
* [`bool process_clicky(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_clicky.c#L79)
|
|
||||||
* [`bool process_haptic(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/2cee371bf125a6ec541dd7c5a809573facc7c456/drivers/haptic/haptic.c#L216)
|
|
||||||
* [`bool process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/card.c#L20)
|
|
||||||
* [`bool process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/keymaps/default/keymap.c#L58)
|
|
||||||
* [`bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/rgb_matrix.c#L139)
|
|
||||||
* [`bool process_midi(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_midi.c#L81)
|
|
||||||
* [`bool process_audio(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_audio.c#L19)
|
|
||||||
* [`bool process_steno(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_steno.c#L160)
|
|
||||||
* [`bool process_music(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_music.c#L114)
|
|
||||||
* [`bool process_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L141)
|
|
||||||
* [`bool process_unicode_common(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicode_common.c#L169)
|
|
||||||
calls one of:
|
|
||||||
* [`bool process_unicode(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicode.c#L20)
|
|
||||||
* [`bool process_unicodemap(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicodemap.c#L46)
|
|
||||||
* [`bool process_ucis(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_ucis.c#L95)
|
|
||||||
* [`bool process_leader(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_leader.c#L51)
|
|
||||||
* [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_combo.c#L115)
|
|
||||||
* [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_printer.c#L77)
|
|
||||||
* [`bool process_auto_shift(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_auto_shift.c#L94)
|
|
||||||
* [`bool process_terminal(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_terminal.c#L264)
|
|
||||||
* [Identify and process Quantum-specific keycodes](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L291)
|
|
||||||
|
|
||||||
At any step during this chain of events a function (such as `process_record_kb()`) can `return false` to halt all further processing.
|
|
||||||
|
|
||||||
<!--
|
|
||||||
#### Mouse Handling
|
|
||||||
|
|
||||||
FIXME: This needs to be written
|
|
||||||
|
|
||||||
#### Serial Link(s)
|
|
||||||
|
|
||||||
FIXME: This needs to be written
|
|
||||||
|
|
||||||
#### Visualizer
|
|
||||||
|
|
||||||
FIXME: This needs to be written
|
|
||||||
|
|
||||||
#### Keyboard state LED's (Caps Lock, Num Lock, Scroll Lock)
|
|
||||||
|
|
||||||
FIXME: This needs to be written
|
|
||||||
|
|
||||||
-->
|
|
@ -1,68 +0,0 @@
|
|||||||
# Unit Testing
|
|
||||||
|
|
||||||
If you are new to unit testing, then you can find many good resources on internet. However most of it is scattered around in small pieces here and there, and there's also many different opinions, so I won't give any recommendations.
|
|
||||||
|
|
||||||
Instead I recommend these two books, explaining two different styles of Unit Testing in detail.
|
|
||||||
|
|
||||||
* "Test Driven Development: By Example: Kent Beck"
|
|
||||||
* "Growing Object-Oriented Software, Guided By Tests: Steve Freeman, Nat Pryce"
|
|
||||||
|
|
||||||
If you prefer videos there are Uncle Bob's [Clean Coders Videos](https://cleancoders.com/), which unfortunately cost quite a bit, especially if you want to watch many of them. But James Shore has a free [Let's Play](http://www.jamesshore.com/Blog/Lets-Play) video series.
|
|
||||||
|
|
||||||
## Google Test and Google Mock
|
|
||||||
It's possible to Unit Test your code using [Google Test](https://github.com/google/googletest). The Google Test framework also includes another component for writing testing mocks and stubs, called "Google Mock". For information how to write the actual tests, please refer to the documentation on that site.
|
|
||||||
|
|
||||||
## Use of C++
|
|
||||||
|
|
||||||
Note that Google Test and therefore any test has to be written in C++, even if the rest of the QMK codebases is written in C. This should hopefully not be a problem even if you don't know any C++, since there's quite clear documentation and examples of the required C++ features, and you can write the rest of the test code almost as you would write normal C. Note that some compiler errors which you might get can look quite scary, but just read carefully what it says, and you should be ok.
|
|
||||||
|
|
||||||
One thing to remember, is that you have to append `extern "C"` around all of your C file includes.
|
|
||||||
|
|
||||||
## Adding Tests for New or Existing Features
|
|
||||||
|
|
||||||
If you want to unit test some feature, then take a look at the existing serial_link tests, in the `quantum/serial_link/tests folder`, and follow the steps below to create a similar structure.
|
|
||||||
|
|
||||||
1. If it doesn't already exist, add a test subfolder to the folder containing the feature.
|
|
||||||
2. Create a `testlist.mk` and a `rules.mk` file in that folder.
|
|
||||||
3. Include those files from the root folder `testlist.mk`and `build_test.mk` respectively.
|
|
||||||
4. Add a new name for your testgroup to the `testlist.mk` file. Each group defined there will be a separate executable. And that's how you can support mocking out different parts. Note that it's worth adding some common prefix, just like it's done for the serial_link tests. The reason for that is that the make command allows substring filtering, so this way you can easily run a subset of the tests.
|
|
||||||
5. Define the source files and required options in the `rules.mk` file.
|
|
||||||
* `_SRC` for source files
|
|
||||||
* `_DEFS` for additional defines
|
|
||||||
* `_INC` for additional include folders
|
|
||||||
6. Write the tests in a new cpp file inside the test folder you created. That file has to be one of the files included from the `rules.mk` file.
|
|
||||||
|
|
||||||
Note how there's several different tests, each mocking out a separate part. Also note that each of them only compiles the very minimum that's needed for the tests. It's recommend that you try to do the same. For a relevant video check out [Matt Hargett "Advanced Unit Testing in C & C++](https://www.youtube.com/watch?v=Wmy6g-aVgZI)
|
|
||||||
|
|
||||||
## Running the Tests
|
|
||||||
|
|
||||||
To run all the tests in the codebase, type `make test`. You can also run test matching a substring by typing `make test:matchingsubstring` Note that the tests are always compiled with the native compiler of your platform, so they are also run like any other program on your computer.
|
|
||||||
|
|
||||||
## Debugging the Tests
|
|
||||||
|
|
||||||
If there are problems with the tests, you can find the executable in the `./build/test` folder. You should be able to run those with GDB or a similar debugger.
|
|
||||||
|
|
||||||
## Full Integration Tests
|
|
||||||
|
|
||||||
It's not yet possible to do a full integration test, where you would compile the whole firmware and define a keymap that you are going to test. However there are plans for doing that, because writing tests that way would probably be easier, at least for people that are not used to unit testing.
|
|
||||||
|
|
||||||
In that model you would emulate the input, and expect a certain output from the emulated keyboard.
|
|
||||||
|
|
||||||
# Tracing Variables
|
|
||||||
|
|
||||||
Sometimes you might wonder why a variable gets changed and where, and this can be quite tricky to track down without having a debugger. It's of course possible to manually add print statements to track it, but you can also enable the variable trace feature. This works for both for variables that are changed by the code, and when the variable is changed by some memory corruption.
|
|
||||||
|
|
||||||
To take the feature into use add `VARIABLE_TRACE=x` to the end of you make command. `x` represents the number of variables you want to trace, which is usually 1.
|
|
||||||
|
|
||||||
Then at a suitable place in the code, call `ADD_TRACED_VARIABLE`, to begin the tracing. For example to trace all the layer changes, you can do this
|
|
||||||
```c
|
|
||||||
void matrix_init_user(void) {
|
|
||||||
ADD_TRACED_VARIABLE("layer", &layer_state, sizeof(layer_state));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This will add a traced variable named "layer" (the name is just for your information), which tracks the memory location of `layer_state`. It tracks 4 bytes (the size of `layer_state`), so any modification to the variable will be reported. By default you can not specify a size bigger than 4, but you can change it by adding `MAX_VARIABLE_TRACE_SIZE=x` to the end of the make command line.
|
|
||||||
|
|
||||||
In order to actually detect changes to the variables you should call `VERIFY_TRACED_VARIABLES` around the code that you think that modifies the variable. If a variable is modified it will tell you between which two `VERIFY_TRACED_VARIABLES` calls the modification happened. You can then add more calls to track it down further. I don't recommend spamming the codebase with calls. It's better to start with a few, and then keep adding them in a binary search fashion. You can also delete the ones you don't need, as each call need to store the file name and line number in the ROM, so you can run out of memory if you add too many calls.
|
|
||||||
|
|
||||||
Also remember to delete all the tracing code once you have found the bug, as you wouldn't want to create a pull request with tracing code.
|
|
@ -1,160 +0,0 @@
|
|||||||
USB NKRO MEMO
|
|
||||||
=============
|
|
||||||
2010/12/09
|
|
||||||
|
|
||||||
|
|
||||||
References
|
|
||||||
----------
|
|
||||||
USB - boot mode, NKRO, compatibility, etc...
|
|
||||||
http://geekhack.org/showthread.php?t=13162
|
|
||||||
NKey Rollover - Overview, Testing Methodology, and Results
|
|
||||||
http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results
|
|
||||||
dfj's NKRO(2010/06)
|
|
||||||
http://geekhack.org/showpost.php?p=191195&postcount=251
|
|
||||||
http://geekhack.org/showthread.php?p=204389#post204389
|
|
||||||
|
|
||||||
|
|
||||||
Terminology
|
|
||||||
---------
|
|
||||||
NKRO
|
|
||||||
ghost
|
|
||||||
matrix
|
|
||||||
mechanical with diodes
|
|
||||||
membrane
|
|
||||||
|
|
||||||
|
|
||||||
OS Support Status
|
|
||||||
-----------------
|
|
||||||
USB NKRO is possible *without* a custom driver.
|
|
||||||
At least following OS's supports.
|
|
||||||
Windows7 64bit
|
|
||||||
WindowsXP
|
|
||||||
Windows2000 SP4
|
|
||||||
Ubuntu10.4(Linux 2.6)
|
|
||||||
MacOSX(To be tested)
|
|
||||||
|
|
||||||
|
|
||||||
Custom Driver for USB NKRO
|
|
||||||
--------------------------
|
|
||||||
NOT NEEDED
|
|
||||||
at least when using following report formats on Windows, Linux or MacOSX.
|
|
||||||
|
|
||||||
|
|
||||||
USB NKRO methods
|
|
||||||
----------------
|
|
||||||
1. Virtual keyboards
|
|
||||||
Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report.
|
|
||||||
If the keyboard has 2 virtual keyboard with Standard report(6KRO), it gets 12KRO.
|
|
||||||
Using this method means the keyboard is a composite device.
|
|
||||||
|
|
||||||
2. Extended report
|
|
||||||
It needs large report size for this method to achieve NKRO.
|
|
||||||
If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient.
|
|
||||||
|
|
||||||
3. Bitmap report
|
|
||||||
If the keyboard has less than 128keys, 16byte report will be enough for NKRO.
|
|
||||||
The 16byte report seems to be reasonable cost to get NKRO.
|
|
||||||
|
|
||||||
|
|
||||||
Report Format
|
|
||||||
-------------
|
|
||||||
Other report formats than followings are possible, though these format are typical one.
|
|
||||||
|
|
||||||
1. Standard 8bytes
|
|
||||||
modifiers(bitmap) 1byte
|
|
||||||
reserved 1byte(not used)
|
|
||||||
keys(array) 1byte*6
|
|
||||||
Standard report can send 6keys plus 8modifiers simultaneously.
|
|
||||||
Standard report is used by most keyboards in the marketplace.
|
|
||||||
Standard report is identical to boot protocol report.
|
|
||||||
Standard report is hard to suffer from compatibility problems.
|
|
||||||
|
|
||||||
2. Extended standard 16,32,64bytes
|
|
||||||
modifiers(bitmap) 1byte
|
|
||||||
reserved 1byte(not used)
|
|
||||||
keys(array) 1byte*(14,32,62)
|
|
||||||
Extended report can send N-keys by using N+2bytes.
|
|
||||||
Extended report is expected to be compatible with boot protocol.
|
|
||||||
|
|
||||||
3. Bitmap 16,32,64bytes
|
|
||||||
keys(bitmap) (16,32)bytes
|
|
||||||
Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes.
|
|
||||||
Bitmap report can achieve USB NKRO efficiently in terms of report size.
|
|
||||||
Bitmap report needs a deliberation for boot protocol implementation.
|
|
||||||
Bitmap report descriptor sample:
|
|
||||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
|
||||||
0x09, 0x06, // Usage (Keyboard),
|
|
||||||
0xA1, 0x01, // Collection (Application),
|
|
||||||
// bitmap of modifiers
|
|
||||||
0x75, 0x01, // Report Size (1),
|
|
||||||
0x95, 0x08, // Report Count (8),
|
|
||||||
0x05, 0x07, // Usage Page (Key Codes),
|
|
||||||
0x19, 0xE0, // Usage Minimum (224),
|
|
||||||
0x29, 0xE7, // Usage Maximum (231),
|
|
||||||
0x15, 0x00, // Logical Minimum (0),
|
|
||||||
0x25, 0x01, // Logical Maximum (1),
|
|
||||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
|
|
||||||
// LED output report
|
|
||||||
0x95, 0x05, // Report Count (5),
|
|
||||||
0x75, 0x01, // Report Size (1),
|
|
||||||
0x05, 0x08, // Usage Page (LEDs),
|
|
||||||
0x19, 0x01, // Usage Minimum (1),
|
|
||||||
0x29, 0x05, // Usage Maximum (5),
|
|
||||||
0x91, 0x02, // Output (Data, Variable, Absolute),
|
|
||||||
0x95, 0x01, // Report Count (1),
|
|
||||||
0x75, 0x03, // Report Size (3),
|
|
||||||
0x91, 0x03, // Output (Constant),
|
|
||||||
// bitmap of keys
|
|
||||||
0x95, (REPORT_BYTES-1)*8, // Report Count (),
|
|
||||||
0x75, 0x01, // Report Size (1),
|
|
||||||
0x15, 0x00, // Logical Minimum (0),
|
|
||||||
0x25, 0x01, // Logical Maximum(1),
|
|
||||||
0x05, 0x07, // Usage Page (Key Codes),
|
|
||||||
0x19, 0x00, // Usage Minimum (0),
|
|
||||||
0x29, (REPORT_BYTES-1)*8-1, // Usage Maximum (),
|
|
||||||
0x81, 0x02, // Input (Data, Variable, Absolute),
|
|
||||||
0xc0 // End Collection
|
|
||||||
where REPORT_BYTES is a report size in bytes.
|
|
||||||
|
|
||||||
|
|
||||||
Considerations
|
|
||||||
--------------
|
|
||||||
Compatibility
|
|
||||||
boot protocol
|
|
||||||
minor/old system
|
|
||||||
Some BIOS doesn't send SET_PROTOCOL request, a keyboard can't switch to boot protocol mode.
|
|
||||||
This may cause a problem on a keyboard which uses other report than Standard.
|
|
||||||
Reactivity
|
|
||||||
USB polling time
|
|
||||||
OS/Driver processing time
|
|
||||||
|
|
||||||
|
|
||||||
Windows Problem
|
|
||||||
---------------
|
|
||||||
1. Windows accepts only 6keys in case of Standard report.
|
|
||||||
It should be able to send 6keys plus 8modifiers.
|
|
||||||
2. Windows accepts only 10keys in case of 16bytes Extended report.
|
|
||||||
It should be able to send 14keys plus 8modifiers.
|
|
||||||
3. Windows accepts only 18keys in case of 32bytes Extended report.
|
|
||||||
It should be able to send 30keys plus 8modifiers.
|
|
||||||
If keys are pressed in excess of the number, wrong keys are registered on Windows.
|
|
||||||
|
|
||||||
This problem will be reportedly fixed soon.(2010/12/05)
|
|
||||||
http://forums.anandtech.com/showpost.php?p=30873364&postcount=17
|
|
||||||
|
|
||||||
|
|
||||||
Tools for testing NKRO
|
|
||||||
----------------------
|
|
||||||
Browser App:
|
|
||||||
http://www.microsoft.com/appliedsciences/content/projects/KeyboardGhostingDemo.aspx
|
|
||||||
http://random.xem.us/rollover.html
|
|
||||||
|
|
||||||
Windows:
|
|
||||||
AquaKeyTest.exe http://geekhack.org/showthread.php?t=6643
|
|
||||||
|
|
||||||
Linux:
|
|
||||||
xkeycaps
|
|
||||||
xev
|
|
||||||
showkeys
|
|
||||||
|
|
||||||
EOF
|
|
Loading…
Reference in new issue