", 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".
-```
-
-Esto nos dice que tenemos un conflicto de merge, y nos dice el nombre del archivo con el conflict. Abre el archivo en tu editor de texto, y en alguna parte del archivo verás algo así:
-
-```
-<<<<<<< HEAD
-For help with any issues, email us at support@webhost.us.
-=======
-Need help? Email support@webhost.us.
->>>>>>> Commit #1
-```
-La línea `<<<<<<< HEAD` marca el principio de un conflicto de merge, y la línea `>>>>>>> Commit #1` marca el final, con las secciones de conflicto separadas por `=======`. La parte del lado `HEAD` is de la versión de QMK master del archivo, y la parte marcada con el mensaje de commit es de la rama actual.
-
-Ya que Git rastrea *cambios de archivos* en vez del contenido de los archivos directamente, si Git no puede encontrar el texto que estaba en el archivo antes del último commit, no sabrá cómo editar el archivo. El editar el archivo de nuevo resolverá este conflicto. Haz tus cambios, y guarda el archivo.
-
-```
-Need help? Email support@webhost.us.
-```
-
-Ahora ejecuta:
-
-```
-git add conflicting_file_1.txt
-git rebase --continue
-```
-
-Git registra los cambios al archivo con conflictos, y sigue aplicando los commits de nuestra rama hasta llegar al final.
diff --git a/docs/es/newbs_building_firmware.md b/docs/es/newbs_building_firmware.md
deleted file mode 100644
index ff9873c785e..00000000000
--- a/docs/es/newbs_building_firmware.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Construyendo tu primer firmware
-
-Ahora que has configurado tu entorno de construcción estas listo para empezar a construir firmwares personalizados. Para esta sección de la guía alternaremos entre 3 programas - tu gestor de ficheros, tu editor de texto , y tu ventana de terminal. Manten los 3 abiertos hasta que hayas acabado y estés contento con el firmware de tu teclado.
-
-Si has cerrado y reabierto la ventana de tu terminal después de seguir el primero paso de esta guía, no olvides hacer `cd qmk_firmware` para que tu terminal esté en el directorio correcto.
-
-## Navega a tu carpeta de keymaps
-
-Comienza navegando a la carpeta `keymaps` correspondiente a tu teclado.
-
-?> Si estás en macOS o Windows hay comandos que puedes utilizar fácilmente para abrir la carpeta keymaps.
-
-?> macOS:
-
- abre keyboards//keymaps
-
-?> Windows:
-
- inicia .\\keyboards\\\\keymaps
-
-## Crea una copia del keymap `default`
-
-Una vez que tengas la carpeta `keymaps` abierta querrás crear una copia de la carpeta `default`. Recomendamos encarecidamente que nombres la carpeta igual que tu nombre de usuario de GitHub, pero puedes utilizar el nombre que quieras siempre que contenga sólo letras en minúscula, números y el caracter de guión bajo.
-
-Para automatizar el proceso, también tienes la opción de ejecutar el script `new_keymap.sh`.
-
-Navega a la carpeta `qmk_firmware/util` e introduce lo siguiente:
-
-```
-./new_keymap.sh
-```
-
-Por ejemplo, para un usuario llamado John, intentando hacer un keymap nuevo para el 1up60hse, tendría que teclear
-
-```
-./new_keymap.sh 1upkeyboards/1up60hse john
-```
-
-## Abre `keymap.c` con tu editor de texto favorito
-
-Abre tu `keymap.c`. Dentro de este fichero encontrarás la estructura que controla cómo se comporta tu teclado. En lo alto de `keymap.c` puede haber distintos defines y enums que hacen el keymap más fácil de leer. Continuando por abajo encontrarás una línea con este aspecto:
-
- const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-
-Esta línea indica el comienzo del listado de Capas. Debajo encontrarás líneas que contienen o bien `LAYOUT` o `KEYMAP`, y estas líneas indican el comienzo de una capa. Debajo de esa línea está la lista de teclas que pertenecen a esa capa concreta.
-
-!> Cuando estés editando tu fichero de keymap ten cuidado con no añadir ni eliminar ninguna coma. Si lo haces el firmware dejará de compilar y puede no ser fácil averiguar dónde está la coma faltante o sobrante.
-
-## Personaliza el Layout a tu gusto
-
-Cómo completar esta paso depende enteramente de ti. Haz ese pequeño cambio que querías o rehaz completamente todo. Puedes eliminar capas si no las necesitas todas, o añadir nuevas hasta un total de 32. Comprueba la siguiente documentación para descubrir qué es lo que puedes definir aquí:
-
-* [Keycodes](keycodes.md)
-* [Características](features.md)
-* [Preguntas frecuentes](faq.md)
-
-?> Mientras estás descubriendo cómo funcionan los keymaps, haz pequeños cambios. Cambios mayores pueden hacer difícil la depuración de problemas que puedan aparecer.
-
-## Construye tu firmware
-
-Cuando los cambios a tu keymap están completos necesitarás construir el firmware. Para hacerlo vuelve a la ventana de tu terminal y ejecuta el siguiente comando:
-
- make :
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un planck rev5, utilizarás el siguiente comando:
-
- make planck/rev5:xyverz
-
-Mientras compila, recibirás un montón de información de salida en la pantalla informándote de qué ficheros están siendo compilados. Debería acabar con una información similar a esta:
-
-```
-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
-```
-
-## Flashea tu firmware
-
-Continua con [Flasheando el firmware](newbs_flashing.md) para aprender cómo escribir tu firmware nuevo en tu teclado.
diff --git a/docs/es/newbs_building_firmware_configurator.md b/docs/es/newbs_building_firmware_configurator.md
deleted file mode 100644
index 60d67f5fa4f..00000000000
--- a/docs/es/newbs_building_firmware_configurator.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# Configurador QMK
-
-El [Configurador QMK](https://config.qmk.fm) es un entorno gráfico online que genera ficheros hexadecimales de Firmware QMK.
-
-?> **Por favor sigue estos pasos en orden.**
-
-Ve el [Video tutorial](https://www.youtube.com/watch?v=-imgglzDMdY)
-
-El Configurador QMK functiona mejor con Chrome/Firefox.
-
-
-!> **Ficheros de otras herramientas como KLE, o kbfirmware no serán compatibles con el Configurador QMK. No las cargues, no las importes. El configurador Configurador QMK es una herramienta DIFERENTE. **
-
-## Seleccionando tu teclado
-
-Haz click en el desplegable y selecciona el teclado para el que quieres crear el keymap.
-
-?> Si tu teclado tiene varias versiones, asegúrate de que seleccionas la correcta.**
-
-Lo diré otra vez porque es importante
-
-!> **ASEGÚRATE DE QUE SELECCIONAS LA VERSIÓN CORRECTA!**
-
-Si se ha anunciado que tu teclado funciona con QMK pero no está en la lista, es probable que un desarrollador no se haya encargado de él aún o que todavía no hemos tenido la oportunidad de incluirlo. Abre un issue en [qmk_firmware](https://github.com/qmk/qmk_firmware/issues) solicitando soportar ese teclado un particular, si no hay un [Pull Request](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) activo para ello. Hay también teclados que funcionan con QMK que están en las cuentas de GitHub de sus manufacturantes. Acuérdate de comprobar esto también.
-
-## Eligiendo el layout de tu teclado
-
-Elige el layout que mejor represente el keymap que quieres crear. Algunos teclados no tienen suficientes layouts o layouts correctos definidos aún. Serán soportados en el futuro.
-
-## Nombre del keymap
-
-Llama a este keymap como quieras.
-
-?> Si estás teniendo problemas para compilar, puede merecer la pena probar un cambio de nombre, ya que puede que ya exista en el repositorio de QMK Firmware.
-
-## Creando Tu keymap
-
-La adición de keycodes se puede hacer de 3 maneras.
-1. Arrastrando y soltando
-2. Clickando en un hueco vacío en el layout y haciendo click en el keycode que deseas
-3. Clickando en un hueco vacío en el layout, presionando la tecla física en tu teclado.
-
-Mueve el puntero de tu ratón sobre una tecla y un pequeño extracto te dirá que es lo que hace la tecla. Para una descripción más detallada por favor, mira
-
-[Referencia básica de keycodes](https://docs.qmk.fm/#/keycodes_basic)
-[Referencia avanzada de keycodes](https://docs.qmk.fm/#/feature_advanced_keycodes)
-
-En el caso de que no puedas encontrar un layout que suporte tu keymap, por ejemplo, tres huecos para la barra espaciadora, dos huecos para el retroceso o dos huecos para shift etc etc, rellènalos TODOS.
-
-### Ejemplo:
-
-3 huecos para barra espaciadora: Rellena TODOS con barra espaciadora
-
-2 huecos para retroceso: Rellena AMBOS con retroceso
-
-2 huecos para el shift derecho: Rellena AMBOS con shift derecho
-
-1 hueco para el shift izquierdo y 1 hueco para soporte iso: Rellena ambos con el shift izquierdo
-
-5 huecos , pero sólo 4 teclas: Intuye y comprueba o pregunta a alguien que lo haya hecho anteriormente.
-
-## Guardando tu keymap para ediciones futuras
-
-Cuando estés satisfecho con un teclado o quieres trabajar en el después, pulsa el botón `Exportar Keymap`. Guardára tu keymap con el nombre que elijas seguido de .json.
-
-Entonces podrás cargar este fichero .json en el futuro pulsando el botón `Importar Keymap`.
-
-!> **PRECAUCIÓN:** No es el mismo tipo de fichero .json usado en kbfirmware.com ni ninguna otra herramienta. Si intentas utilizar un fichero .json de alguna de estas herramientas con el Configurador QMK, existe la posibilidad de que tu teclado **explote**.
-
-## Generando tu fichero de firmware
-
-Pulsa el botón verde `Compilar`.
-
-Cuando la compilación haya acabado, podrás presionar el botón verde `Descargar Firmware`.
-
-## Flasheando tu teclado
-
-Por favor, dirígete a la sección de [Flashear firmware](newbs_flashing.md)
-
-## Problemas comunes
-
-#### Mi fichero .json no funciona
-
-Si el fichero .json fue generado con el Configurador QMK, enhorabuena, has dado con un bug. Abre una issue en [qmk_configurator](https://github.com/qmk/qmk_configurator/issues)
-
-Si no....cómo no viste el mensaje en negrita que puse arriba diciendo que no hay que utilizar otros ficheros .json?
-
-#### Hay espacios extra en mi layout ¿Qué hago?
-
-Si te refieres a tener tres espacios para la barra espaciadora, la mejor decisión es rellenar los tres con la barra espaciadora. También se puede hacer lo mismo con las teclas retroceso y las de shift
-
-#### Para qué sirve el keycode.......
-
-Por favor, mira
-
-[Referencia básica de keycodes](https://docs.qmk.fm/#/keycodes_basic)
-[Referencia avanzada de keycodes](https://docs.qmk.fm/#/feature_advanced_keycodes)
-
-#### No compila
-
-Por favor, revisa las otras capas de tu keymap para asegurarte de que no hay teclas aleatorias presentes.
-
-## Problemas y bugs
-
-Siempre aceptamos peticiones de clientes y reportes de bug. Por favor, indícalos en [qmk_configurator](https://github.com/qmk/qmk_configurator/issues)
diff --git a/docs/es/newbs_flashing.md b/docs/es/newbs_flashing.md
deleted file mode 100644
index 066715c4830..00000000000
--- a/docs/es/newbs_flashing.md
+++ /dev/null
@@ -1,351 +0,0 @@
-# Flasheando tu teclado
-
-Ahora que has construido tu fichero de firmware personalizado querrás flashear tu teclado.
-
-## Flasheando tu teclado con QMK Toolbox
-
-La manera más simple de flashear tu teclado sería con [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases).
-
-De todos modos, QMK Toolbox actualmente sólo está disponible para Windows y macOS. Si estás usando Linux (o sólo quisieras flashear el firmware desde la línea de comandos), tendrás que utilizar el [método indicado abajo](newbs_flashing.md#flash-your-keyboard-from-the-command-line).
-
-### Cargar el fichero en QMK Toolbox
-
-Empieza abriendo la aplicación QMK Toolbox. Tendrás que buscar el fichero de firmware usando Finder o Explorer. El firmware de teclado puede estar en uno de estos dos formatos- `.hex` o `.bin`. QMK intenta copiar el apropiado para tu teclado en el fichero raíz `qmk_firmware`.
-
-?> Si tu estás on Windows o macOS hay comandos que puedes usar para abrir fácilmente la carpeta del firmware actual en Explorer o Finder.
-
-?> Windows:
-
- start .
-
-?> macOS:
-
- open .
-
-El fichero de firmware sempre sigue el siguiente formato de nombre:
-
- _.{bin,hex}
-
-Por ejemplo, un `plank/rev5` con un keymap `default` tendrá este nombre de fichero:
-
- planck_rev5_default.hex
-
-Una vez que hayas localizado el fichero de tu firmware arrástralo a la caja "Fichero local" en QMK Toolbox, o haz click en "Abrir" y navega allí donde tengas almacenado tu fichero de firmware.
-
-### Pon tu teclado en modo DFU (Bootloader)
-
-Para poder flashear tu firmware personalizado tienes que poner tu teclado en un modo especial que permite flasheado. Cuando está en este modo no podrás teclear o utilizarlo para ninguna otra cosa. Es muy importante que no desconectes tu teclado, de lo contrario interrumpirás el proceso de flasheo mientras el firmware se está escribiendo.
-
-Diferentes teclados tienen diferentes maneras de entrar en este modo especial. Si tu PCB actualmente ejecuta QMK o TMK y no has recibido instrucciones específicas, intenta los siguientes pasos en orden:
-
-* Manten pulsadas ambas teclas shift y pulsa `Pause`
-* Manten pulsadas ambas teclas shift y pulsa `B`
-* Desconecta tu teclado, mantén pulsada la barra espaciadora y `B` al mismo tiempo, conecta tu teclado y espera un segundo antes de dejar de pulsar las teclas
-* Pulsa el botón físico `RESET` situado en el fondo de la PCB
-* Localiza los pines en la PCB etiquetados on `BOOT0` o `RESET`, puentea estos dos juntos cuando enchufes la PCB
-
-Si has tenido éxito verás un mensaje similar a este en QMK Toolbox:
-
-```
-*** Clueboard - Clueboard 66% HotSwap disconnected -- 0xC1ED:0x2390
-*** DFU device connected
-```
-
-### Flashea tu teclado
-
-Haz click en el botón `Flash` de QMK Toolbox. Verás una información de salida similar a esta:
-
-```
-*** 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
-```
-
-## Flashea tu teclado desde la línea de comandos
-
-Lo primero que tienes que saber es qué bootloader utiliza tu teclado. Hay cuatro bootloaders pincipales que se usan habitualmente . Pro-Micro y sus clones usan CATERINA, Teensy's usa Halfkay, las placas OLKB usan QMK-DFU, y otros chips atmega32u4 usan DFU.
-
-Puedes encontrar más información sobre bootloaders en la página [Instrucciones de flasheado e información de Bootloader](flashing.md).
-
-Si sabes qué bootloader estás usando, en el momento de compilar el firmware, podrás añadir algún texto extra al comando `make` para automatizar el proceso de flasheado.
-
-### DFU
-
-Para eo bootloader DFU, cuando estés listo para compilar y flashear tu firmware, abre tu ventana de terminal y ejecuta el siguiente comando de construcción:
-
- make ::dfu
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un planck rev5, utilizarás este comando:
-
- make planck/rev5:xyverz:dfu
-
-Una vez que finalice de compilar, deberá aparecer lo siguiente:
-
-```
-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
- ```
-
-Después de llegar a este punto, el script de construcción buscará el bootloader DFU cada 5 segundos. Repetirá lo siguiente hasta que se encuentre el dispositivo o lo canceles:
-
- dfu-programmer: no device present.
- Error: Bootloader not found. Trying again in 5s.
-
-Una vez haya hecho esto, tendrás que reiniciar el controlador. Debería mostrar una información de salida similar a esta:
-
-```
-*** 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
-```
-
-?> Si tienes problemas con esto- del estilo de `dfu-programmer: no device present` - por favor consulta las [Preguntas frecuentes de construcción](faq_build.md).
-
-#### Comandos DFU
-
-Hay un número de comandos DFU que puedes usar para flashear firmware a un dispositivo DFU:
-
-* `:dfu` - Esta es la opción normal y espera hasta que un dispositivo DFU esté disponible, entonces flashea el firmware. Esperará reintentando cada 5 segundos, para ver si un dispositivo DFU ha aparecido.
-* `:dfu-ee` - Esta flashea un fichero `eep` en vez del hex normal. Esto no es lo común.
-* `:dfu-split-left` - Esta flashea el firmware normal, igual que la opción por defecto (`:dfu`). Sin embargo, también flashea el fichero EEPROM "Lado Izquierdo" para teclados divididos. _Esto es ideal para los ficheros divididos basados en Elite C._
-* `:dfu-split-right` - Esto flashea el firmware normal, igual que la opción por defecto (`:dfu`). Sin embargo, también flashea el fichero EEPROM "Lado Derecho" para teclados divididos. _Esto es ideal para los ficheros divididos basados en Elite C._
-
-
-### Caterina
-
-Para placas Arduino y sus clones (como la SparkFun ProMicro), cuando estés listo para compilar y flashear tu firmware, abre tu ventana de terminal y ejecuta el siguiente comando de construcción:
-
- make ::avrdude
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un Lets Split rev2, usarás este comando:
-
- make lets_split/rev2:xyverz:avrdude
-
-Una vez que finalice de compilar, deberá aparecer lo siguiente:
-
-```
-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..............
-```
-
-En este punto, reinicia la placa y entonces el script detectará el bootloader y procederá a flashear la placa. La información de salida deber ser algo similar a esto:
-
-```
-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.
-```
-Si tienes problemas con esto, puede ser necesario que hagas esto:
-
- sudo make ::avrdude
-
-
-Adicionalmente, si quisieras flashear múltiples placas, usa el siguiente comando:
-
- make ::avrdude-loop
-
-Cuando hayas acabado de flashear placas, necesitarás pulsar Ctrl + C o cualquier combinación que esté definida en tu sistema operativo para finalizar el bucle.
-
-
-### HalfKay
-
-Para dispositivos PJRC (Teensy's), cuando estés listo para compilar y flashear tu firmware, abre tu ventana de terminal y ejecuta el siguiente comando de construcción:
-
- make ::teensy
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un Ergodox o un Ergodox EZ, usarás este comando:
-
- make ergodox_ez:xyverz:teensy
-
-Una vez que el firmware acabe de compilar, deberá mostrar una información de salida como esta:
-
-```
-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)
- ```
-
-En este punto, reinicia tu placa. Una vez que lo hayas hecho, deberás ver una información de salida como esta:
-
- ```
- Found HalfKay Bootloader
-Read "./.build/ergodox_ez_xyverz.hex": 28532 bytes, 88.5% usage
-Programming............................................................................................................................................................................
-...................................................
-Booting
-```
-
-### BootloadHID
-
-Para placas basadas en Bootmapper Client(BMC)/bootloadHID/ATmega32A, cuando estés listo para compilar y flashear tu firmware, abre tu ventana de terminal y ejecuta el comando de construcción:
-
- make ::bootloaderHID
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un jj40, usarás esté comando:
-
- make jj40:xyverz:bootloaderHID
-
-Una vez que el firmware acaba de compilar, mostrará una información de salida como esta:
-
-```
-Linking: .build/jj40_default.elf [OK]
-Creating load file for flashing: .build/jj40_default.hex [OK]
-Copying jj40_default.hex to qmk_firmware folder [OK]
-Checking file size of jj40_default.hex [OK]
- * The firmware size is fine - 21920/28672 (6752 bytes free)
-```
-
-Después de llegar a este punto, el script de construcción buscará el bootloader DFU cada 5 segundos. Repetirá lo siguiente hasta que se encuentre el dispositivo o hasta que lo canceles.
-
-```
-Error opening HIDBoot device: The specified device was not found
-Trying again in 5s.
-```
-
-Una vez que lo haga, querrás reinicar el controlador. Debería entonces mostrar una información de salida similar a esta:
-
-```
-Page size = 128 (0x80)
-Device size = 32768 (0x8000); 30720 bytes remaining
-Uploading 22016 (0x5600) bytes starting at 0 (0x0)
-0x05580 ... 0x05600
-```
-
-### STM32 (ARM)
-
-Para la mayoría de placas ARM (incluyendo la Proton C, Planck Rev 6, y Preonic Rev 3), cuando estés listo para compilar y flashear tu firmware, abre tu ventana de terminal y ejecuta el siguiente comando de construcción:
-
- make ::dfu-util
-
-Por ejemplo, si tu keymap se llama "xyverz" y estás construyendo un keymap para un teclado Planck Revision 6, utilizarás este comando y a continuación reiniciarás el teclado con el bootloader (antes de que acabe de compilar):
-
- make planck/rev6:xyverz:dfu-util
-
-Una vez que el firmware acaba de compilar, mostrará una información de salida similar a esta:
-
-```
-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
-```
-
-#### STM32 Commands
-
-Hay un número de comandos DFU que puedes usar para flashear firmware a un dispositivo DFU:
-
-* `:dfu-util` - El comando por defecto para flashing en dispositivos STM32.
-* `:dfu-util-wait` - Esto funciona como el comando por defecto, pero te da (configurable) 10 segundos de tiempo antes de que intente flashear el firmware. Puedes usar `TIME_DELAY=20` desde la líena de comandos para cambiar este tiempo de retardo.
- * Eg: `make ::dfu-util TIME_DELAY=5`
-* `:dfu-util-split-left` - Flashea el firmware normal, igual que la opción por defecto (`:dfu-util`). Sin embargo, también flashea el fichero EEPROM "Lado Izquierdo" para teclados divididos.
-* `:dfu-util-split-right` - Flashea el firmware normal, igual que la opción por defecto (`:dfu-util`). Sin embargo, también flashea el fichero EEPROM "Lado Derecho" para teclados divididos.
-
-## ¡Pruébalo!
-
-¡Felicidades! ¡Tu firmware personalizado ha sido programado en tu teclado!
-
-Pruébalo y asegúrate de que todo funciona de la manera que tu quieres. Hemos escrito [Testeando y depurando](newbs_testing_debugging.md) para redondear esta guía de novatos, así que pásate por allí para aprender cómo resolver problemas con tu funcionalidad personalizada.
diff --git a/docs/es/newbs_getting_started.md b/docs/es/newbs_getting_started.md
deleted file mode 100644
index 046fdee27ec..00000000000
--- a/docs/es/newbs_getting_started.md
+++ /dev/null
@@ -1,103 +0,0 @@
-# Introducción
-
-El teclado de tu computador tiene un procesador dentro de él, no muy distinto del que está dentro de tu ordenador. Este procesador ejecuta software que es responsable de detectar la pulsación de las teclas y enviar informes sobre el estado del teclado cuando las teclas son pulsadas y liberadas. QMK ocupa el rol de ese software. Cuando construyes un keymap personalizado , estas creando el equivalente de un programa ejecutable en tu teclado.
-
-QMK intenta poner un montón de poder en tus manos haciendo que las cosas fáciles sean fáciles, y las cosas difíciles posibles. No tienes que saber cómo programar para crear keymaps potentes — sólo tienes que seguir un conjunto simple de reglas sintácticas.
-
-# Comenzando
-
-Antes de que puedas construir keymaps, necesitarás instalar algun software y configurar tu entorno de construcción. Esto sólo hay que hacerlo una vez sin importar en cuántos teclados planeas configurar el software.
-
-Si prefieres hacerlo mediante un interfaz gráfico , por favor, considera utilizar el [Configurador QMK](https://config.qmk.fm). En ese caso dirígete a [Construyendo tu primer firmware usando la GUI](newbs_building_firmware_configurator.md).
-
-
-## Descarga el software
-
-### Editor de texto
-
-Necesitarás un programa con el que puedas editar y guardar archivos de **texto plano**, en windows puedes utilizar Notepad y en tu Linux puedes utilizar gedit. Estos dos programas son editores simples y funcionales. En macOS ten cuidado con la aplicación de edición de texto por defecto TextEdit: no guardará texto plano a menos de que se le seleccione explícitamente _Make Plain Text_ desde el menú _Format_.
-
-También puedes descargar e instalar un editor de texto dedicado como [Sublime Text](https://www.sublimetext.com/) o [VS Code](https://code.visualstudio.com/). Esta es probablemente la mejor manera independientemente de la plataforma, ya que estos programas fueron creados específicamente para editar código.
-
-?> ¿No estás seguro de qué editor de texto utilizar? Laurence Bradford escribió una [estupenda introducción](https://learntocodewith.me/programming/basics/text-editors/) al tema.
-
-### 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)
-
-## Configura tu entorno
-
-Hemos intentado hacer QMK lo más fácil de configurar posible. Sólo tienes que preparar tu entorno Linux o Unix, y luego dejar que QMK
-instale el resto.
-
-?> Si no has trabajado con la línea de comandos de Linux/Unix con anterioridad, hay algunos conceptos y comandos básicos que deberías aprender. Estos recursos te enseñarán lo suficiente para poder trabajar con QMK:
-[Comandos de Linux que debería saber](https://www.guru99.com/must-know-linux-commands.html)
-[Algunos comandos básicos de Unix](https://www.tjhsst.edu/~dhyatt/superap/unixcmd.html)
-
-### Windows
-
-Necesitarás instalar MSYS2 y Git.
-
-* Sigue las instrucciones de instalación en la [página de MSYS2](https://www.msys2.org).
-* Cierra las terminales abiertas de MSYS2 y abre una nueva termial de MSYS2 MinGW 64-bit.
-* Instala Git ejecutando este comando: `pacman -S git`.
-
-### macOS
-
-Necesitarás instalar Homebrew. Sigue las instrucciones que encontrarás en la [página de Homebrew](https://brew.sh).
-
-Despueś de que se haya inastalado Homebrew, continúa con _Set Up QMK_. En ese paso ejecutará un script que instalará el resto de paquetes.
-
-### Linux
-
-Necesitarás instalar Git. Es bastante probable que ya lo tengas, pero si no, uno de los siguientes comandos debería instalarlo:
-
-* Debian / Ubuntu / Devuan: `apt-get install git`
-* Fedora / Red Hat / CentOS: `yum install git`
-* Arch: `pacman -S git`
-
-?> Docker es también una opción en todas las plataformas. [Haz click aquí si quieres detalles.](getting_started_build_tools.md#docker)
-
-## Configura QMK
-
-Una vez que hayas configurado tu entorno Linux/Unix, estarás listo para descargar QMK. Haremos esto utilizando Git para "clonar" el respositorio de QMK. Abre una ventana de Terminal o MSYS2 MinGW y mantenla abierta mientras sigues esta guía. Dentro de esa ventana ejecuta estos dos comandos:
-
-```shell
-git clone --recurse-submodules https://github.com/qmk/qmk_firmware.git
-cd qmk_firmware
-```
-
-?> Si ya sabes [cómo usar GitHub](getting_started_github.md), te recomendamos en vez de eso, crees y clones tu propio fork. Si no sabes lo que significa, puedes ignorar este mensaje sin problemas.
-
-QMK viene con un script para ayudarte a configurar el resto de cosas que necesitarás. Deberías ejecutarlo introduciendo este comando:
-
- util/qmk_install.sh
-
-## Prueba tu entorno de construcción
-
-Ahora que tu entorno de construcción de QMK está configurado, puedes construcir un firmware para tu teclado. Comienza intentado construir el keymap por defecto del teclado. Deberías ser capaz de hacerlo con un comando con este formato:
-
- make :default
-
-Por ejemplo, para construir el firmware para un Clueboard 66% deberías usar:
-
- make clueboard/66/rev3:default
-
-Cuando esté hecho, deberías tener un montón de información de salida similar a esta:
-
-```
-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)
-```
-
-# Creando tu keymap
-
-Ya estás listo para crear tu propio keymap personal! Para hacerlo continua con [Construyendo tu primer firmware](newbs_building_firmware.md).
diff --git a/docs/es/newbs_learn_more_resources.md b/docs/es/newbs_learn_more_resources.md
deleted file mode 100644
index 34fd7556bf1..00000000000
--- a/docs/es/newbs_learn_more_resources.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Recursos de aprendizaje
-
-Estos recursos procuran dar miembros nuevos en la communidad QMK un mayor entendimiento de la información proporcionada en la documentación para novatos.
-
-Recursos de Git:
-
-* [Excelente tutorial general](https://www.codecademy.com/learn/learn-git)
-* [Juego de Git para aprender usando ejemplos](https://learngitbranching.js.org/)
-* [Recursos de Git para aprender más sobre GitHub](getting_started_github.md)
-* [Recursos de Git dirigidos específicamente a QMK](contributing.md)
-
-
-Recursos para línea de mandatos:
-
-* [Excelente tutorial general sobre la línea de mandatos](https://www.codecademy.com/learn/learn-the-command-line)
diff --git a/docs/es/newbs_testing_debugging.md b/docs/es/newbs_testing_debugging.md
deleted file mode 100644
index 69f6984658e..00000000000
--- a/docs/es/newbs_testing_debugging.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Testeando y depurando
-
-Una vez que hayas flasheado tu teclado con un firmware personalizado estarás listo para probarlo. Con un poco de suerte todo funcionará a la primera, pero si no es así, este documento te ayudará a averiguar qué está mal.
-
-## Probando
-
-Probar tu teclado es generalmente bastante sencillo. Persiona cada una de las teclas y asegúrate de que envía la tecla correcta. Existen incluso programas que te ayudarán a asegurarte de que no te dejas ninguna tecla sin comprobar.
-
-Nota: Estos programas no los provée ni están relacionados con QMK.
-
-* [Switch Hitter](https://elitekeyboards.com/switchhitter.php) (Sólo Windows)
-* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Sólo Mac)
-* [Keyboard Tester](https://www.keyboardtester.com) (Aplicación web)
-* [Keyboard Checker](https://keyboardchecker.com) (Aplicación web)
-
-## Depurando
-
-Tu teclado mostrará información de depuración si tienes `CONSOLE_ENABLE = yes` en tu `rules.mk`. Por defecto la información de salida es muy limitada, pero puedes encender el modo de depuración para incrementar la información de salida. Utiliza el keycode `DEBUG` de tu keymap, usa la característica [Comando](feature_command.md) para activar el modo depuración, o añade el siguiente código a tu 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;
-}
-```
-
-### Depurando con QMK Toolbox
-
-Para plataformas compatibles, [QMK Toolbox](https://github.com/qmk/qmk_toolbox) se puede usar para mostrar mensajes de depuración de tu teclado.
-
-### Depurando con hid_listen
-
-¿Prefieres una solución basada en una terminal? [hid_listen](https://www.pjrc.com/teensy/hid_listen.html), provista por PJRC, se puede usar también para mostrar mensajes de depuración. Hay binarios preconstruídos para Windows,Linux,y MacOS.
-
-
-
-## Enviando tus propios mensajes de depuración
-
-A veces, es útil imprimir mensajes de depuración desde tu [código personalizado](custom_quantum_functions.md). Hacerlo es bastante simple. Comienza incluyendo `print.h` al principio de tu fichero:
-
-```c
-#include "print.h"
-```
-
-Después de eso puedes utilzar algunas funciones print diferentes:
-
-* `print("string")`: Imprime un string simple
-* `uprintf("%s string", var)`: Imprime un string formateado
-* `dprint("string")` Imprime un string simple, pero sólo cuando el modo de depuración está activo
-* `dprintf("%s string", var)`: Imprime un string formateado, pero sólo cuando el modo de depuración está activo
-
-## Ejemplos de depuración
-
-Debajo hay una colección de ejemplos de depuración del mundo real. Para información adicional, Dirígete a [Depurando/Encontrando problemas en QMK](faq_debug.md).
-
-### ¿Que posición en la matriz tiene esta pulsación de tecla?
-
-Cuando estés portando, o intentando diagnosticar problemas en la pcb, puede ser útil saber si la pulsación de una tecla es escaneada correctamente. Para hablitar la información de registro en este escenario, añade el siguiente código al `keymap.c` de tus keymaps
-
-```c
-bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- // If console is enabled, it will print the matrix position and status of each key pressed
-#ifdef CONSOLE_ENABLE
- uprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
-#endif
- return true;
-}
-```
-
-Ejemplo de salida
-```text
-Waiting for device:.......
-Listening:
-KL: kc: 169, col: 0, row: 0, pressed: 1
-KL: kc: 169, col: 0, row: 0, pressed: 0
-KL: kc: 174, col: 1, row: 0, pressed: 1
-KL: kc: 174, col: 1, row: 0, pressed: 0
-KL: kc: 172, col: 2, row: 0, pressed: 1
-KL: kc: 172, col: 2, row: 0, pressed: 0
-```
-
-### ¿Cuanto tiempo tardó en escanear la pulsación de una tecla?
-
-Cuando estés probando problemas en el rendimiento, puede ser útil saber la frecuenta a la cual la matríz de pulsadores se está escaneando. Para hablitar la información de registro en este escenario, añade el siguiente código al `config.h` de tus keymaps
-
-```c
-#define DEBUG_MATRIX_SCAN_RATE
-```
-
-Ejemplo de salida
-```text
- > matrix scan frequency: 315
- > matrix scan frequency: 313
- > matrix scan frequency: 316
- > matrix scan frequency: 316
- > matrix scan frequency: 316
- > matrix scan frequency: 316
-```
diff --git a/docs/faq_debug.md b/docs/faq_debug.md
index 1afa38a6243..fba27c5f683 100644
--- a/docs/faq_debug.md
+++ b/docs/faq_debug.md
@@ -18,15 +18,19 @@ void keyboard_post_init_user(void) {
## Debugging Tools
-There are two different tools you can use to debug your keyboard.
+Various tools are available to debug your keyboard.
### Debugging With QMK Toolbox
For compatible platforms, [QMK Toolbox](https://github.com/qmk/qmk_toolbox) can be used to display debug messages from your keyboard.
+### Debugging with QMK CLI
+
+Prefer a terminal based solution? The [QMK CLI console command](cli_commands.md#qmk-console) can be used to display debug messages from your keyboard.
+
### Debugging With hid_listen
-Prefer a terminal based solution? [hid_listen](https://www.pjrc.com/teensy/hid_listen.html), provided by PJRC, can also be used to display debug messages. Prebuilt binaries for Windows,Linux,and MacOS are available.
+Something stand-alone? [hid_listen](https://www.pjrc.com/teensy/hid_listen.html), provided by PJRC, can also be used to display debug messages. Prebuilt binaries for Windows,Linux,and MacOS are available.
## Sending Your Own Debug Messages :id=debug-api
@@ -62,7 +66,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
```
Example output
-```text
+```
Waiting for device:.......
Listening:
KL: kc: 169, col: 0, row: 0, pressed: 1
@@ -82,7 +86,7 @@ When testing performance issues, it can be useful to know the frequency at which
```
Example output
-```text
+```
> matrix scan frequency: 315
> matrix scan frequency: 313
> matrix scan frequency: 316
diff --git a/docs/faq_keymap.md b/docs/faq_keymap.md
index dbeadba7100..01ded4f2319 100644
--- a/docs/faq_keymap.md
+++ b/docs/faq_keymap.md
@@ -19,7 +19,7 @@ There are 3 standard keyboard layouts in use around the world- ANSI, ISO, and JI
Sometimes, for readability's sake, it's useful to define custom names for some keycodes. People often define custom names using `#define`. For example:
```c
-#define FN_CAPS LT(_FL, KC_CAPSLOCK)
+#define FN_CAPS LT(_FL, KC_CAPS)
#define ALT_TAB LALT(KC_TAB)
```
@@ -38,8 +38,8 @@ As a quick fix try holding down `Space`+`Backspace` while you plug in your keybo
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'.
+## `KC_SYSTEM_REQUEST` Isn't Working
+Use keycode for Print Screen (`KC_PRINT_SCREEN`/`KC_PSCR`) instead of `KC_SYSTEM_REQUEST`. Key combination of 'Alt + Print Screen' is recognized as 'System request'.
See [issue #168](https://github.com/tmk/tmk_keyboard/issues/168) and
* https://en.wikipedia.org/wiki/Magic_SysRq_key
@@ -47,7 +47,7 @@ See [issue #168](https://github.com/tmk/tmk_keyboard/issues/168) and
## 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.
+Somewhat confusingly, there are two "Power" keycodes in QMK: `KC_KB_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.
@@ -57,7 +57,7 @@ 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.
+For Modifier keys and layer actions you have to place `KC_TRNS` 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
* https://geekhack.org/index.php?topic=57008.msg1492604#msg1492604
@@ -75,7 +75,7 @@ This feature is for *mechanical lock switch* like [this Alps one](https://deskth
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`.***
+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_NUM` and `KC_SCRL`.***
## Input Special Characters Other Than ASCII like Cédille 'Ç'
diff --git a/docs/faq_misc.md b/docs/faq_misc.md
index 9ab2b69a809..9e34a048156 100644
--- a/docs/faq_misc.md
+++ b/docs/faq_misc.md
@@ -36,7 +36,7 @@ Size after:
can retry, loading that one
- Some of the options you might specify in your keyboard's Makefile
consume extra memory; watch out for BOOTMAGIC_ENABLE,
- MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, CONSOLE_ENABLE, API_SYSEX_ENABLE
+ MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, CONSOLE_ENABLE
- DFU tools do /not/ allow you to write into the bootloader (unless
you throw in an extra fruit salad of options), so there is little risk
there.
@@ -49,10 +49,6 @@ First you have to compile firmware with the build option `NKRO_ENABLE` in **Make
Try `Magic` **N** command(`LShift+RShift+N` by default) when **NKRO** still doesn't work. You can use this command to toggle between **NKRO** and **6KRO** mode temporarily. In some situations **NKRO** doesn't work and you will need to switch to **6KRO** mode, in particular when you are in BIOS.
-If your firmware was built with `BOOTMAGIC_ENABLE` you need to turn its switch on by `BootMagic` **N** command(`Space+N` by default). This setting is stored in EEPROM and kept over power cycles.
-
-https://github.com/tmk/tmk_keyboard#boot-magic-configuration---virtual-dip-switch
-
## TrackPoint Needs Reset Circuit (PS/2 Mouse Support)
Without reset circuit you will have inconsistent result due to improper initialization of the hardware. See circuit schematic of TPM754:
diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
index ec7eeaaa0ca..99b0ca3c8a3 100644
--- a/docs/feature_auto_shift.md
+++ b/docs/feature_auto_shift.md
@@ -26,20 +26,26 @@ down will repeat the shifted key, though this can be disabled with
once then immediately (within `TAPPING_TERM`) hold it down again (this works
with the shifted value as well if auto-repeat is disabled).
+There are also the `get_auto_shift_repeat` and `get_auto_shift_no_auto_repeat`
+functions for more granular control. Neither will have an effect unless
+`AUTO_SHIFT_REPEAT_PER_KEY` or `AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY` respectively
+are defined.
+
## Are There Limitations to Auto Shift?
Yes, unfortunately.
-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.
-
-Additionally, with keyrepeat the desired shift state can get mixed up. It will
-always 'belong' to the last key pressed. For example, keyrepeating a capital
-and then tapping something lowercase (whether or not it's an Auto Shift key)
-will result in the capital's *key* still being held, but shift not.
+1. 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.
+2. Additionally, with keyrepeat the desired shift state can get mixed up. It will
+ always 'belong' to the last key pressed. For example, keyrepeating a capital
+ and then tapping something lowercase (whether or not it's an Auto Shift key)
+ will result in the capital's *key* still being held, but shift not.
+3. Auto Shift does not apply to Tap Hold keys. For automatic shifting of Tap Hold
+ keys see [Retro Shift](#retro-shift).
## How Do I Enable Auto Shift?
@@ -96,6 +102,34 @@ 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!
+For more granular control of this feature, you can add the following to your `config.h`:
+
+```c
+#define AUTO_SHIFT_TIMEOUT_PER_KEY
+```
+
+You can then add the following function to your keymap:
+
+```c
+uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) {
+ switch(keycode) {
+ case AUTO_SHIFT_NUMERIC:
+ return 2 * get_generic_autoshift_timeout();
+ case AUTO_SHIFT_SPECIAL:
+ return get_generic_autoshift_timeout() + 50;
+ case AUTO_SHIFT_ALPHA:
+ default:
+ return get_generic_autoshift_timeout();
+ }
+}
+```
+
+Note that you cannot override individual keys that are in one of those groups
+if you are using them; trying to add a case for `KC_A` in the above example will
+not compile as `AUTO_SHIFT_ALPHA` is there. A possible solution is a second switch
+above to handle individual keys with no default case and only referencing the
+groups in the below fallback switch.
+
### NO_AUTO_SHIFT_SPECIAL (simple define)
Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
@@ -109,11 +143,24 @@ Do not Auto Shift numeric keys, zero through nine.
Do not Auto Shift alpha characters, which include A through Z.
-### Auto Shift Per Key
+### Auto Shift Per Key
-This is a function that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
+There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
-The default function looks like this:
+The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`:
+
+```c
+bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
+ switch(keycode) {
+ case KC_DOT:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+For more granular control, there is `get_auto_shifted_key`. The default function looks like this:
```c
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
@@ -127,13 +174,14 @@ bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
# ifndef NO_AUTO_SHIFT_SPECIAL
case KC_TAB:
case KC_MINUS ... KC_SLASH:
- case KC_NONUS_BSLASH:
+ case KC_NONUS_BACKSLASH:
# endif
return true;
}
- return false;
+ return get_custom_auto_shifted_key(keycode, record);
}
```
+
This functionality is enabled by default, and does not need a define.
### AUTO_SHIFT_REPEAT (simple define)
@@ -144,6 +192,106 @@ Enables keyrepeat.
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
+## Custom Shifted Values
+
+Especially on small keyboards, the default shifted value for many keys is not
+optimal. To provide more customizability, there are two user-definable
+functions, `autoshift_press/release_user`. These register or unregister the
+correct value for the passed key. Below is an example adding period to Auto
+Shift and making its shifted value exclamation point. Make sure to use weak
+mods - setting real would make any keys following it use their shifted values
+as if you were holding the key. Clearing of modifiers is handled by Auto Shift,
+and the OS-sent shift value if keyrepeating multiple keys is always that of
+the last key pressed (whether or not it's an Auto Shift key).
+
+You can also have non-shifted keys for the shifted values (or even no shifted
+value), just don't set a shift modifier!
+
+```c
+bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
+ switch(keycode) {
+ case KC_DOT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
+ switch(keycode) {
+ case KC_DOT:
+ register_code16((!shifted) ? KC_DOT : KC_EXLM);
+ break;
+ default:
+ if (shifted) {
+ add_weak_mods(MOD_BIT(KC_LSFT));
+ }
+ // & 0xFF gets the Tap key for Tap Holds, required when using Retro Shift
+ register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
+ }
+}
+
+void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
+ switch(keycode) {
+ case KC_DOT:
+ unregister_code16((!shifted) ? KC_DOT : KC_EXLM);
+ break;
+ default:
+ // & 0xFF gets the Tap key for Tap Holds, required when using Retro Shift
+ // The IS_RETRO check isn't really necessary here, always using
+ // keycode & 0xFF would be fine.
+ unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
+ }
+}
+```
+
+## Retro Shift
+
+Holding and releasing a Tap Hold key without pressing another key will ordinarily
+result in only the hold. With `retro shift` enabled this action will instead
+produce a shifted version of the tap keycode on release.
+
+It does not require [Retro Tapping](tap_hold.md#retro-tapping) to be enabled, and
+if both are enabled the state of `retro tapping` will only apply if the tap keycode
+is not matched by Auto Shift. `RETRO_TAPPING_PER_KEY` and its corresponding
+function, however, are checked before `retro shift` is applied.
+
+To enable `retro shift`, add the following to your `config.h`:
+
+```c
+#define RETRO_SHIFT
+```
+
+If `RETRO_SHIFT` is defined to a value, hold times greater than that value will
+not produce a tap on release for Mod Taps, and instead triggers the hold action.
+This enables modifiers to be held for combining with mouse clicks without
+generating taps on release. For example:
+
+```c
+#define RETRO_SHIFT 500
+```
+
+This value (if set) must be greater than one's `TAPPING_TERM`, as the key press
+must be designated as a 'hold' by `process_tapping` before we send the modifier.
+There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys.
+
+### Retro Shift and Tap Hold Configurations
+
+Tap Hold Configurations work a little differently when using Retro Shift.
+Referencing `TAPPING_TERM` makes little sense, as holding longer would result in
+shifting one of the keys.
+
+`IGNORE_MOD_TAP_INTERRUPT` changes *only* rolling from a mod tap (releasing it
+first), sending both keys instead of the modifier on the second. Its effects on
+nested presses are ignored.
+
+As nested taps were changed to act as though `PERMISSIVE_HOLD` is set unless only
+`IGNORE_MOD_TAP_INTERRUPT` is (outside of Retro Shift), and Retro Shift ignores
+`IGNORE_MOD_TAP_INTERRUPT`, `PERMISSIVE_HOLD` has no effect on Mod Taps.
+
+Nested taps will *always* act as though the `TAPPING_TERM` was exceeded for both
+Mod and Layer Tap keys.
+
## Using Auto Shift Setup
This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index d47ecc68242..79782cf5649 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -8,7 +8,7 @@ The MCU can only supply so much current to its GPIO pins. Instead of powering th
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:
-```makefile
+```make
BACKLIGHT_ENABLE = yes
```
@@ -54,7 +54,7 @@ If backlight breathing is enabled (see below), the following functions are also
To select which driver to use, configure your `rules.mk` with the following:
-```makefile
+```make
BACKLIGHT_DRIVER = software
```
@@ -87,7 +87,7 @@ This functionality is configured at the keyboard level with the `BACKLIGHT_ON_ST
The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
-```makefile
+```make
BACKLIGHT_DRIVER = pwm
```
@@ -143,7 +143,7 @@ The breathing effect is the same as in the hardware PWM implementation.
While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
-```makefile
+```make
BACKLIGHT_DRIVER = pwm
```
@@ -167,7 +167,7 @@ Currently only hardware PWM is supported, not timer assisted, and does not provi
In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your `rules.mk`:
-```makefile
+```make
BACKLIGHT_DRIVER = software
```
@@ -188,7 +188,7 @@ To activate multiple backlight pins, add something like this to your `config.h`,
If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using this simple API provided by QMK. To enable, add this to your `rules.mk`:
-```makefile
+```make
BACKLIGHT_DRIVER = custom
```
diff --git a/docs/feature_bluetooth.md b/docs/feature_bluetooth.md
index 08e5f24ac55..d4ed494053b 100644
--- a/docs/feature_bluetooth.md
+++ b/docs/feature_bluetooth.md
@@ -4,10 +4,10 @@
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
-|Board |Bluetooth Protocol |Connection Type |rules.mk |Bluetooth Chip|
-|----------------------------------------------------------------|----------------------------|----------------|---------------------------|--------------|
-|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic | UART |`BLUETOOTH = RN42` | RN-42 |
-|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy | SPI |`BLUETOOTH = AdafruitBLE` | nRF51822 |
+|Board |Bluetooth Protocol |Connection Type|rules.mk |Bluetooth Chip|
+|----------------------------------------------------------------|--------------------|---------------|--------------------------------|--------------|
+|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic |UART |`BLUETOOTH_DRIVER = RN42` |RN-42 |
+|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy|SPI |`BLUETOOTH_DRIVER = BluefruitLE`|nRF51822 |
Not Supported Yet but possible:
* [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479). [Possible tmk implementation found in](https://github.com/tmk/tmk_keyboard/issues/514)
@@ -16,23 +16,24 @@ Not Supported Yet but possible:
* 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
+Currently The only bluetooth chipset supported by QMK is the Adafruit Bluefruit SPI Friend. It's a Nordic nRF51822 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 BLUEFRUIT_LE_RST_PIN D4`
+* `#define BLUEFRUIT_LE_CS_PIN B4`
+* `#define BLUEFRUIT_LE_IRQ_PIN 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.
-
## Bluetooth Rules.mk Options
The currently supported Bluetooth chipsets do not support [N-Key Rollover (NKRO)](reference_glossary.md#n-key-rollover-nkro), so `rules.mk` must contain `NKRO_ENABLE = no`.
-Use only one of these to enable Bluetooth:
-* BLUETOOTH_ENABLE = yes (Legacy Option)
-* BLUETOOTH = RN42
-* BLUETOOTH = AdafruitBLE
+Add the following to your `rules.mk`:
+
+```make
+BLUETOOTH_ENABLE = yes
+BLUETOOTH_DRIVER = BluefruitLE # or RN42
+```
## Bluetooth Keycodes
diff --git a/docs/feature_bootmagic.md b/docs/feature_bootmagic.md
index 6c66b00679a..148ea92b9e2 100644
--- a/docs/feature_bootmagic.md
+++ b/docs/feature_bootmagic.md
@@ -8,8 +8,6 @@ On some keyboards Bootmagic Lite is disabled by default. If this is the case, it
BOOTMAGIC_ENABLE = yes
```
-?> You may see `lite` being used in place of `yes`.
-
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
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index d98e6f2ac7d..c0e10f09d5a 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -56,7 +56,7 @@ combo_t key_combos[COMBO_COUNT] = {
[AB_ESC] = COMBO(ab_combo, KC_ESC),
[JK_TAB] = COMBO(jk_combo, KC_TAB),
[QW_SFT] = COMBO(qw_combo, KC_LSFT)
- [SD_LAYER] = COMBO(layer_combo, MO(_LAYER)),
+ [SD_LAYER] = COMBO(sd_combo, MO(_LAYER)),
};
```
@@ -100,7 +100,7 @@ void process_combo_event(uint16_t combo_index, bool pressed) {
This will send "john.doe@example.com" if you chord E and M together, and clear the current line with Backspace and Left-Shift. You could change this to do stuff like play sounds or change settings.
-It is worth noting that `COMBO_ACTION`s are not needed anymore. As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to run your own custom keycodes from combos. Just define the custom keycode, program its functionality in `process_record_user`, and define a combo with `COMBO(, )`.
+It is worth noting that `COMBO_ACTION`s are not needed anymore. As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to run your own custom keycodes from combos. Just define the custom keycode, program its functionality in `process_record_user`, and define a combo with `COMBO(, )`. See the first example in [Macros](feature_macros.md).
## Keycodes
You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game. The following keycodes are available for use in your `keymap.c`
@@ -141,10 +141,13 @@ Processing combos has two buffers, one for the key presses, another for the comb
## Modifier Combos
If a combo resolves to a Modifier, the window for processing the combo can be extended independently from normal combos. By default, this is disabled but can be enabled with `#define COMBO_MUST_HOLD_MODS`, and the time window can be configured with `#define COMBO_HOLD_TERM 150` (default: `TAPPING_TERM`). With `COMBO_MUST_HOLD_MODS`, you cannot tap the combo any more which makes the combo less prone to misfires.
-## Per Combo Timing, Holding and Tapping
-For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, or if it needs to be tapped.
+## Strict key press order
+By defining `COMBO_MUST_PRESS_IN_ORDER` combos only activate when the keys are pressed in the same order as they are defined in the key array.
-For example, tap-only combos are useful if any (or all) of the underlying keys is a Mod-Tap or a Layer-Tap key. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't actually activate. Instead the keys are processed separately as if the combo wasn't even there.
+## Per Combo Timing, Holding, Tapping and Key Press Order
+For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, if it needs to be tapped, or if its keys need to be pressed in order.
+
+For example, tap-only combos are useful if any (or all) of the underlying keys are mod-tap or layer-tap keys. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't activate. Instead the keys are processed separately as if the combo wasn't even there.
In order to use these features, the following configuration options and functions need to be defined. Coming up with useful timings and configuration is left as an exercise for the reader.
@@ -153,6 +156,7 @@ In order to use these features, the following configuration options and function
| `COMBO_TERM_PER_COMBO` | uint16_t get_combo_term(uint16_t index, combo_t \*combo) | Optional per-combo timeout window. (default: `COMBO_TERM`) |
| `COMBO_MUST_HOLD_PER_COMBO` | bool get_combo_must_hold(uint16_t index, combo_t \*combo) | Controls if a given combo should fire immediately on tap or if it needs to be held. (default: `false`) |
| `COMBO_MUST_TAP_PER_COMBO` | bool get_combo_must_tap(uint16_t index, combo_t \*combo) | Controls if a given combo should fire only if tapped within `COMBO_HOLD_TERM`. (default: `false`) |
+| `COMBO_MUST_PRESS_IN_ORDER_PER_COMBO` | bool get_combo_must_press_in_order(uint16_t index, combo_t \*combo) | Controls if a given combo should fire only if its keys are pressed in order. (default: `true`) |
Examples:
```c
@@ -173,7 +177,7 @@ uint16_t get_combo_term(uint16_t index, combo_t *combo) {
// i.e. the exact array of keys you defined for the combo.
// This can be useful if your combos have a common key and you want to apply the
// same combo term for all of them.
- if (combo->keys[0] == KC_ENTER) { // if first key in the array is KC_ENTER
+ if (combo->keys[0] == KC_ENT) { // if first key in the array is Enter
return 150;
}
@@ -216,6 +220,38 @@ bool get_combo_must_tap(uint16_t index, combo_t *combo) {
return false;
}
+
+bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) {
+ switch (combo_index) {
+ /* List combos here that you want to only activate if their keys
+ * are pressed in the same order as they are defined in the combo's key
+ * array. */
+ case COMBO_NAME_HERE:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+## Generic hook to (dis)allow a combo activation
+
+By defining `COMBO_SHOULD_TRIGGER` and its companying function `bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record)` you can block or allow combos to activate on the conditions of your choice.
+For example, you could disallow some combos on the base layer and allow them on another. Or disable combos on the home row when a timer is running.
+
+Examples:
+```c
+bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record) {
+ /* Disable combo `SOME_COMBO` on layer `_LAYER_A` */
+ switch (combo_index) {
+ case SOME_COMBO:
+ if (layer_state_is(_LAYER_A)) {
+ return false;
+ }
+ }
+
+ return true;
+}
```
## Variable Length Combos
diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md
index f37a785b1e7..9cd736a24ac 100644
--- a/docs/feature_debounce_type.md
+++ b/docs/feature_debounce_type.md
@@ -116,6 +116,7 @@ Where name of algorithm is one of:
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
+* ```sym_defer_pr``` - debouncing per row. On any state change, a per-row timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that row, the entire row is pushed. Can improve responsiveness over `sym_defer_g` while being less susceptible than per-key debouncers to noise.
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
diff --git a/docs/feature_digitizer.md b/docs/feature_digitizer.md
index 9b6aeddbaa9..ac2d64f9777 100644
--- a/docs/feature_digitizer.md
+++ b/docs/feature_digitizer.md
@@ -4,7 +4,7 @@ The digitizer HID interface allows setting the mouse cursor position at absolute
To enable the digitizer interface, add the following line to your rules.mk:
-```makefile
+```make
DIGITIZER_ENABLE = yes
```
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 509f55b917e..6a1a3750a6c 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -70,22 +70,61 @@ or `keymap.c`:
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) { /* First encoder */
if (clockwise) {
- tap_code(KC_PGDN);
+ tap_code_delay(KC_VOLU, 10);
} else {
- tap_code(KC_PGUP);
+ tap_code_delay(KC_VOLD, 10);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
- tap_code(KC_DOWN);
+ rgb_matrix_increase_hue();
} else {
- tap_code(KC_UP);
+ rgb_matrix_decrease_hue();
}
}
- return true;
+ return false;
}
```
-!> If you return `true`, this will allow the keyboard level code to run, as well. Returning `false` will override the keyboard level code. Depending on how the keyboard level function is set up.
+!> If you return `true`, it will allow the keyboard level code to run as well. Returning `false` will override the keyboard level code, depending on how the keyboard function is set up.
+
+Layer conditions can also be used with the callback function like the following:
+
+```c
+bool encoder_update_user(uint8_t index, bool clockwise) {
+ if (get_highest_layer(layer_state|default_layer_state) > 0) {
+ if (index == 0) {
+ if (clockwise) {
+ tap_code(KC_WH_D);
+ } else {
+ tap_code(KC_WH_U);
+ }
+ } else if (index == 1) {
+ if (clockwise) {
+ tap_code_delay(KC_VOLU, 10);
+ } else {
+ tap_code_delay(KC_VOLD, 10);
+ }
+ }
+ } else { /* Layer 0 */
+ if (index == 0) {
+ if (clockwise) {
+ tap_code(KC_PGDN);
+ } else {
+ tap_code(KC_PGUP);
+ }
+ } else if (index == 1) {
+ if (clockwise) {
+ rgb_matrix_increase_speed();
+ } else {
+ rgb_matrix_decrease_speed();
+ }
+ }
+ }
+ return false;
+}
+```
+
+?> Media and mouse countrol keycodes such as `KC_VOLU` and `KC_WH_D` requires `EXTRAKEY_ENABLE = yes` and `MOUSEKEY_ENABLE = yes` respectively in user's `rules.mk` if they are not enabled as default on keyboard level configuration.
## Hardware
@@ -93,7 +132,10 @@ The A an B lines of the encoders should be wired directly to the MCU, and the C/
## Multiple Encoders
-Multiple encoders may share pins so long as each encoder has a distinct pair of pins.
+Multiple encoders may share pins so long as each encoder has a distinct pair of pins when the following conditions are met:
+- using detent encoders
+- pads must be high at the detent stability point which is called 'default position' in QMK
+- no more than two encoders sharing a pin can be turned at the same time
For example you can support two encoders using only 3 pins like this
```
diff --git a/docs/feature_grave_esc.md b/docs/feature_grave_esc.md
index f57c6042ca5..09d098ee4e9 100644
--- a/docs/feature_grave_esc.md
+++ b/docs/feature_grave_esc.md
@@ -4,17 +4,17 @@ If you're using a 60% keyboard, or any other layout with no F-row, you will have
## 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.
+Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) with `QK_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 `
character.
+If Mary presses `QK_GESC` on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple `
character.
## Keycodes
-|Key |Aliases |Description |
-|---------|-----------|------------------------------------------------------------------|
-|`KC_GESC`|`GRAVE_ESC`|Escape when pressed, `
when Shift or GUI are held|
+|Key |Aliases |Description |
+|-----------------|---------|------------------------------------------------------------------|
+|`QK_GRAVE_ESCAPE`|`QK_GESC`|Escape when pressed, `
when Shift or GUI are held|
### Caveats
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index 469c9c79815..63ac4305ff2 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -4,9 +4,22 @@
The following options are currently available for haptic feedback in `rules.mk`:
-`HAPTIC_ENABLE += DRV2605L`
+```
+HAPTIC_ENABLE = yes
+
+HAPTIC_DRIVER += DRV2605L
+HAPTIC_DRIVER += SOLENOID
+```
+
+The following `config.h` settings are available for all types of haptic feedback:
-`HAPTIC_ENABLE += SOLENOID`
+| Settings | Default | Description |
+|--------------------------------------|---------------|---------------------------------------------------------------------------------------------------------------|
+|`HAPTIC_ENABLE_PIN` | *Not defined* |Configures a pin to enable a boost converter for some haptic solution, often used with solenoid drivers. |
+|`HAPTIC_ENABLE_PIN_ACTIVE_LOW` | *Not defined* |If defined then the haptic enable pin is active-low. |
+|`HAPTIC_ENABLE_STATUS_LED` | *Not defined* |Configures a pin to reflect the current enabled/disabled status of haptic feedback. |
+|`HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW` | *Not defined* |If defined then the haptic status led will be active-low. |
+|`HAPTIC_OFF_IN_LOW_POWER` | `0` |If set to `1`, haptic feedback is disabled before the device is configured, and while the device is suspended. |
## Known Supported Hardware
@@ -45,6 +58,7 @@ First you will need a build a circuit to drive the solenoid through a mosfet as
| Settings | Default | Description |
|----------------------------|----------------------|-------------------------------------------------------|
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
+|`SOLENOID_PIN_ACTIVE_LOW` | *Not defined* |If defined then the solenoid trigger pin is active low.|
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
@@ -153,7 +167,7 @@ List of waveform sequences from the datasheet:
```
#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:
+If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
```
#define DRV_MODE_DEFAULT *sequence name or number*
@@ -168,10 +182,14 @@ This mode sets continuous haptic feedback with the option to increase or decreas
The Haptic Exclusion is implemented as `__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record)` in haptic.c. This allows a re-definition at the required level with the specific requirement / exclusion.
### NO_HAPTIC_MOD
-With the entry of `#define NO_HAPTIC_MOD` in config.h, modifiers from Left Control to Right GUI will not trigger a feedback. This also includes modifiers in a Mod Tap configuration.
+With the entry of `#define NO_HAPTIC_MOD` in config.h, the following keys will not trigger feedback:
-### NO_HAPTIC_FN
-With the entry of `#define NO_HAPTIC_FN` in config.h, layer keys will not rigger a feedback.
+* Usual modifier keys such as Control/Shift/Alt/Gui (For example `KC_LCTL`)
+* `MO()` momentary keys. See also [Layers](feature_layers.md).
+* `LM()` momentary keys with mod active.
+* `LT()` layer tap keys, when held to activate a layer. However when tapped, and the key is quickly released, and sends a keycode, haptic feedback is still triggered.
+* `TT()` layer tap toggle keys, when held to activate a layer. However when tapped `TAPPING_TOGGLE` times to permanently toggle the layer, on the last tap haptic feedback is still triggered.
+* `MT()` mod tap keys, when held to keep a usual modifier key pressed. However when tapped, and the key is quickly released, and sends a keycode, haptic feedback is still triggered. See also [Mod-Tap](mod_tap.md).
### NO_HAPTIC_ALPHA
With the entry of `#define NO_HAPTIC_ALPHA` in config.h, none of the alpha keys (A ... Z) will trigger a feedback.
@@ -186,4 +204,4 @@ With the entry of `#define NO_HAPTIC_LOCKKEYS` in config.h, none of the followin
With the entry of `#define NO_HAPTIC_NAV` in config.h, none of the following keys will trigger a feedback: Print Screen, Pause, Insert, Delete, Page Down, Page Up, Left Arrow, Up Arrow, Right Arrow, Down Arrow, End, Home.
### NO_HAPTIC_NUMERIC
-With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback.
\ No newline at end of file
+With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback.
diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md
index 95702d6a239..fe33517a161 100644
--- a/docs/feature_joystick.md
+++ b/docs/feature_joystick.md
@@ -15,7 +15,7 @@ or send gamepad reports based on values computed by the keyboard.
To use analog input you must first enable it in `rules.mk`:
-```makefile
+```make
JOYSTICK_ENABLE = yes
JOYSTICK_DRIVER = analog # or 'digital'
```
diff --git a/docs/feature_key_lock.md b/docs/feature_key_lock.md
index 8e6e29f0e68..76813942298 100644
--- a/docs/feature_key_lock.md
+++ b/docs/feature_key_lock.md
@@ -19,4 +19,5 @@ First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Th
Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
-Switching layers will not cancel the Key Lock.
+Switching layers will not cancel the Key Lock. The Key Lock can be cancelled by calling the `cancel_key_lock()` function.
+
diff --git a/docs/feature_key_overrides.md b/docs/feature_key_overrides.md
index 98036241e33..2417fcf5942 100644
--- a/docs/feature_key_overrides.md
+++ b/docs/feature_key_overrides.md
@@ -39,7 +39,7 @@ For more customization possibilities, you may directly create a `key_override_t`
This shows how the mentioned example of sending `delete` when `shift` + `backspace` are pressed is realized:
```c
-const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPACE, KC_DELETE);
+const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPC, KC_DEL);
// This globally defines all key overrides to be used
const key_override_t **key_overrides = (const key_override_t *[]){
@@ -107,10 +107,10 @@ The [Grave Escape feature](feature_grave_esc.md) is limited in its configurabili
```c
// Shift + esc = ~
-const key_override_t tilde_esc_override = ko_make_basic(MOD_MASK_SHIFT, KC_ESC, S(KC_GRAVE));
+const key_override_t tilde_esc_override = ko_make_basic(MOD_MASK_SHIFT, KC_ESC, S(KC_GRV));
// GUI + esc = `
-const key_override_t grave_esc_override = ko_make_basic(MOD_MASK_GUI, KC_ESC, KC_GRAVE);
+const key_override_t grave_esc_override = ko_make_basic(MOD_MASK_GUI, KC_ESC, KC_GRV);
const key_override_t **key_overrides = (const key_override_t *[]){
&tilde_esc_override,
diff --git a/docs/feature_layers.md b/docs/feature_layers.md
index 78d950dc496..e30c540a79e 100644
--- a/docs/feature_layers.md
+++ b/docs/feature_layers.md
@@ -45,7 +45,7 @@ Once you have a good feel for how layers work and what you can do, you can get m
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).
+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/quantum/action_layer.h).
## Functions :id=functions
diff --git a/docs/feature_layouts.md b/docs/feature_layouts.md
index b34fd442d5c..93d040b5542 100644
--- a/docs/feature_layouts.md
+++ b/docs/feature_layouts.md
@@ -25,7 +25,7 @@ The `layouts/default/` and `layouts/community/` are two examples of layout "repo
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
+```markdown
# 60_ansi
LAYOUT_60_ansi
diff --git a/docs/feature_leader_key.md b/docs/feature_leader_key.md
index f10bca7589f..e5b1e7a4d9e 100644
--- a/docs/feature_leader_key.md
+++ b/docs/feature_leader_key.md
@@ -37,7 +37,7 @@ void matrix_scan_user(void) {
}
```
-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.
+As you can see, you have a few functions. You can use `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS`, `SEQ_THREE_KEYS` up to `SEQ_FIVE_KEYS` for longer sequences.
Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously.
@@ -74,9 +74,9 @@ SEQ_THREE_KEYS(KC_C, KC_C, KC_C) {
## Infinite Leader key timeout
-Sometimes your leader key is not on a comfortable places as the rest of keys on your sequence. Imagine that your leader key is one of your outer top right keys, you may need to reposition your hand just to reach your leader key.
+Sometimes your leader key is not on a comfortable place as the rest of keys on your sequence. Imagine that your leader key is one of your outer top right keys, you may need to reposition your hand just to reach your leader key.
This can make typing the entire sequence on time hard even if you are able to type most of the sequence fast. For example, if your sequence is `Leader + asd` typing `asd` fast is very easy once you have your hands in your home row. However starting the sequence in time after moving your hand out of the home row to reach the leader key and back is not.
-To remove the stress this situation produces to your hands you can enable an infinite timeout just for the leader key. This mean that, after you hit the leader key you will have an infinite amount of time to start the rest of the sequence, allowing you to proper position your hands on the best position to type the rest of the sequence comfortably.
+To remove the stress this situation produces to your hands you can enable an infinite timeout just for the leader key. This means that after you hit the leader key you will have an infinite amount of time to start the rest of the sequence, allowing you to proper position your hands on the best position to type the rest of the sequence comfortably.
This infinite timeout only affects the leader key, so in our previous example of `Leader + asd` you will have an infinite amount of time between `Leader` and `a`, but once you start the sequence the timeout you have configured (global or per key) will work normally.
This way you can configure a very short `LEADER_TIMEOUT` but still have plenty of time to position your hands.
@@ -89,11 +89,11 @@ In order to enable this, place this in your `config.h`:
By default, the Leader Key feature will filter the keycode out of [`Mod-Tap`](mod_tap.md) and [`Layer Tap`](feature_layers.md#switching-and-toggling-layers) functions when checking for the Leader sequences. That means if you're using `LT(3, KC_A)`, it will pick this up as `KC_A` for the sequence, rather than `LT(3, KC_A)`, giving a more expected behavior for newer users.
-While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by added `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This will then disable the filtering, and you'll need to specify the whole keycode.
+While, this may be fine for most, if you want to specify the whole keycode (eg, `LT(3, KC_A)` from the example above) in the sequence, you can enable this by adding `#define LEADER_KEY_STRICT_KEY_PROCESSING` to your `config.h` file. This will then disable the filtering, and you'll need to specify the whole keycode.
## 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 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.
diff --git a/docs/feature_led_indicators.md b/docs/feature_led_indicators.md
index a415b4b4dfc..95d1cd47521 100644
--- a/docs/feature_led_indicators.md
+++ b/docs/feature_led_indicators.md
@@ -1,6 +1,6 @@
# LED Indicators
-?> Currently, this feature is not supported for split keyboards
+?> LED indicators on split keyboards will require state information synced to the slave half (e.g. `#define SPLIT_LED_STATE_ENABLE`). See [data sync options](feature_split_keyboard.md#data-sync-options) for more details.
QMK provides methods to read 5 of the LEDs defined in the HID spec:
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 7d7971bbed4..37c74843aa6 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -49,10 +49,12 @@ Here is an example using 2 drivers.
!> Note the parentheses, this is so when `LED_DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)` will give very different results than `rand() % LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL`.
+For split keyboards using `LED_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
+
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
@@ -65,6 +67,109 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-simple.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ).
+---
+### IS31FLCOMMON :id=is31flcommon
+
+There is basic support for addressable LED matrix lighting with a selection of I2C ISSI Lumissil LED controllers through a shared common driver. To enable it, add this to your `rules.mk`:
+
+```makefile
+LED_MATRIX_ENABLE = yes
+LED_MATRIX_DRIVER =
+```
+
+Where `` is the applicable LED driver chip as below
+
+| Driver Name | Data Sheet | Capability |
+|-------------|------------|------------|
+| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 180 LED, 30x6 Matrix |
+| `ISSIFL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 198 LED, 18x11 Matrix |
+| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 144 LED, 18x8 Matrix |
+| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 72 LED, 18x4 Matrix |
+
+You can use between 1 and 4 IC's. Do not specify `DRIVER_ADDR_` define for IC's if not present on your keyboard. The `DRIVER_ADDR_1` default assumes that all Address pins on the controller have been connected to GND. Drivers that have SYNC functionality have the default settings to disable if 1 driver. If more than 1 drivers then `DRIVER_ADDR_1` will be set to Master and the remaiing ones set to Slave.
+
+Configure the hardware via your `config.h`:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
+| `DRIVER_LED_TOTAL` | (Required) How many LED lights are present across all drivers | |
+| `DRIVER_ADDR_1` | (Optional) Address for the first LED driver | |
+| `DRIVER_ADDR_` | (Required) Address for the additional LED drivers | |
+| `ISSI_SSR_` | (Optional) Configuration for the Spread Spectrum Register | |
+| `ISSI_CONFIGURATION` | (Optional) Configuration for the Configuration Register | |
+| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
+| `ISSI_PULLDOWNUP` | (Optional) Configuration for the Pull Up & Pull Down Register | |
+| `ISSI_TEMP` | (Optional) Configuration for the Tempature Register | |
+| `ISSI_PWM_ENABLE` | (Optional) Configuration for the PWM Enable Register | |
+| `ISSI_PWM_SET` | (Optional) Configuration for the PWM Setting Register | |
+| `ISSI_SCAL_LED ` | (Optional) Configuration for the LEDs Scaling Registers | 0xFF |
+| `ISSI_MANUAL_SCALING` | (Optional) If you wish to configure the Scaling Registers manually | |
+
+
+Defaults
+
+| Variable | IS31FL3742A | IS31FL3743A | IS31FL3745 | IS31FL3746 |
+|----------|-------------|-------------|------------|------------|
+| `DRIVER_ADDR_1` | 0b0110000 | 0b0100000 | 0b0100000 | 0b1100000 |
+| `ISSI_SSR_1` | 0x00 | 0x00 / 0x60 | 0x00 / 0xC0 | 0x00 |
+| `ISSI_SSR_<2-4>` | 0x00 | 0x40 | 0x80 | 0x00 |
+| `ISSI_CONFIGURATION` | 0x31 | 0x01 | 0x31 | 0x01 |
+| `ISSI_PULLDOWNUP` | 0x55 | 0x33 | 0x33 | 0x33 |
+| `ISSI_TEMP` | N/A | 0x00 | 0x00 | 0x00 |
+| `ISSI_PWM_ENABLE` | N/A | N/A | N/A | 0x00 |
+| `ISSI_PWM_SET` | 0x00 | N/A | N/A | 0x00 |
+
+Here is an example using 2 drivers.
+
+```c
+#define DRIVER_ADDR_2 0b0100001
+
+#define DRIVER_COUNT 2
+#define DRIVER_1_LED_TOTAL 66
+#define DRIVER_2_LED_TOTAL 42
+#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
+```
+!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
+
+Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
+
+Define these arrays listing all the LEDs in your `.c`:
+
+```c
+const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+/* Refer to IS31 manual for these locations
+ * driver
+ * | LED address
+ * | | */
+ { 0, CS1_SW1 },
+ { 0, CS2_SW1 },
+ // ...
+}
+```
+
+Where `CSx_SWx` is the location of the LED in the matrix defined by the datasheet. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
+
+`ISSI_MANUAL_SCALING` is used to override the Scaling for individual LED's. By default they will be set as per `ISSI_SCAL_LED`. In `config.h` set how many LED's you want to manually set scaling for.
+Eg `#define ISSI_MANUAL_SCALING 3`
+
+Then Define the array listing all the LEDs you want to override in your `.c`:
+
+```c
+const is31_led __flash g_is31_scaling[ISSI_MANUAL_SCALING] = {
+ * LED Index
+ * | Scaling
+ * | | */
+ {5, 120},
+ {9, 120},
+ ....
+}
+```
+
+Where LED Index is the position of the LED in the `g_is31_leds` array. The `scaling` value between 0 and 255 to be written to the Scaling Register.
+
---
## Common Configuration :id=common-configuration
@@ -164,26 +269,26 @@ You can disable a single effect by defining `DISABLE_[EFFECT_NAME]` in your `con
|Define |Description |
|-------------------------------------------------------|-----------------------------------------------|
-|`#define DISABLE_LED_MATRIX_ALPHAS_MODS` |Disables `LED_MATRIX_ALPHAS_MODS` |
-|`#define DISABLE_LED_MATRIX_BREATHING` |Disables `LED_MATRIX_BREATHING` |
-|`#define DISABLE_LED_MATRIX_BAND` |Disables `LED_MATRIX_BAND` |
-|`#define DISABLE_LED_MATRIX_BAND_PINWHEEL` |Disables `LED_MATRIX_BAND_PINWHEEL` |
-|`#define DISABLE_LED_MATRIX_BAND_SPIRAL` |Disables `LED_MATRIX_BAND_SPIRAL` |
-|`#define DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT` |Disables `LED_MATRIX_CYCLE_LEFT_RIGHT` |
-|`#define DISABLE_LED_MATRIX_CYCLE_UP_DOWN` |Disables `LED_MATRIX_CYCLE_UP_DOWN` |
-|`#define DISABLE_LED_MATRIX_CYCLE_OUT_IN` |Disables `LED_MATRIX_CYCLE_OUT_IN` |
-|`#define DISABLE_LED_MATRIX_DUAL_BEACON` |Disables `LED_MATRIX_DUAL_BEACON` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Disables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE` |Disables `LED_MATRIX_SOLID_REACTIVE_WIDE` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE` |Disables `LED_MATRIX_SOLID_REACTIVE_MULTIWIDE` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS` |Disables `LED_MATRIX_SOLID_REACTIVE_CROSS` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS` |Disables `LED_MATRIX_SOLID_REACTIVE_MULTICROSS`|
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS` |Disables `LED_MATRIX_SOLID_REACTIVE_NEXUS` |
-|`#define DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS` |Disables `LED_MATRIX_SOLID_REACTIVE_MULTINEXUS`|
-|`#define DISABLE_LED_MATRIX_SOLID_SPLASH` |Disables `LED_MATRIX_SOLID_SPLASH` |
-|`#define DISABLE_LED_MATRIX_SOLID_MULTISPLASH` |Disables `LED_MATRIX_SOLID_MULTISPLASH` |
-|`#define DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT` |Disables `LED_MATRIX_WAVE_LEFT_RIGHT` |
-|`#define DISABLE_LED_MATRIX_WAVE_UP_DOWN` |Disables `LED_MATRIX_WAVE_UP_DOWN` |
+|`#define ENABLE_LED_MATRIX_ALPHAS_MODS` |Enables `LED_MATRIX_ALPHAS_MODS` |
+|`#define ENABLE_LED_MATRIX_BREATHING` |Enables `LED_MATRIX_BREATHING` |
+|`#define ENABLE_LED_MATRIX_BAND` |Enables `LED_MATRIX_BAND` |
+|`#define ENABLE_LED_MATRIX_BAND_PINWHEEL` |Enables `LED_MATRIX_BAND_PINWHEEL` |
+|`#define ENABLE_LED_MATRIX_BAND_SPIRAL` |Enables `LED_MATRIX_BAND_SPIRAL` |
+|`#define ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT` |Enables `LED_MATRIX_CYCLE_LEFT_RIGHT` |
+|`#define ENABLE_LED_MATRIX_CYCLE_UP_DOWN` |Enables `LED_MATRIX_CYCLE_UP_DOWN` |
+|`#define ENABLE_LED_MATRIX_CYCLE_OUT_IN` |Enables `LED_MATRIX_CYCLE_OUT_IN` |
+|`#define ENABLE_LED_MATRIX_DUAL_BEACON` |Enables `LED_MATRIX_DUAL_BEACON` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE` |Enables `LED_MATRIX_SOLID_REACTIVE_WIDE` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE` |Enables `LED_MATRIX_SOLID_REACTIVE_MULTIWIDE` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS` |Enables `LED_MATRIX_SOLID_REACTIVE_CROSS` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS` |Enables `LED_MATRIX_SOLID_REACTIVE_MULTICROSS`|
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS` |Enables `LED_MATRIX_SOLID_REACTIVE_NEXUS` |
+|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS` |Enables `LED_MATRIX_SOLID_REACTIVE_MULTINEXUS`|
+|`#define ENABLE_LED_MATRIX_SOLID_SPLASH` |Enables `LED_MATRIX_SOLID_SPLASH` |
+|`#define ENABLE_LED_MATRIX_SOLID_MULTISPLASH` |Enables `LED_MATRIX_SOLID_MULTISPLASH` |
+|`#define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT` |Enables `LED_MATRIX_WAVE_LEFT_RIGHT` |
+|`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` |
## Custom LED Matrix Effects :id=custom-led-matrix-effects
@@ -219,7 +324,7 @@ static bool my_cool_effect(effect_params_t* params) {
for (uint8_t i = led_min; i < led_max; i++) {
led_matrix_set_value(i, 0xFF);
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
// e.g: A more complex effect, relying on external methods and state, with
@@ -233,8 +338,7 @@ static bool my_cool_effect2_complex_run(effect_params_t* params) {
for (uint8_t i = led_min; i < led_max; i++) {
led_matrix_set_value(i, some_global_state++);
}
-
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
static bool my_cool_effect2(effect_params_t* params) {
if (params->init) my_cool_effect2_complex_init(params);
@@ -244,14 +348,7 @@ static bool my_cool_effect2(effect_params_t* params) {
#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
```
-For inspiration and examples, check out the built-in effects under `quantum/led_matrix_animations/`
-
-
-
-
-
-
-
+For inspiration and examples, check out the built-in effects under `quantum/led_matrix/animations/`.
## Additional `config.h` Options :id=additional-configh-options
@@ -339,7 +436,7 @@ Where `28` is an unused index from `eeconfig.h`.
If you want to set custom indicators, such as an LED for Caps Lock, or layer indication, you can use the `led_matrix_indicators_kb` or `led_matrix_indicators_user` function for that:
```c
void led_matrix_indicators_kb(void) {
- led_matrix_set_color(index, value);
+ led_matrix_set_value(index, value);
}
```
diff --git a/docs/feature_macros.md b/docs/feature_macros.md
index 3660f377559..78bc4ba0a50 100644
--- a/docs/feature_macros.md
+++ b/docs/feature_macros.md
@@ -4,7 +4,107 @@ Macros allow you to send multiple keystrokes when pressing just one key. QMK has
!> **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.
-## `SEND_STRING()` & `process_record_user`
+## Using Macros In JSON Keymaps
+
+You can define up to 32 macros in a `keymap.json` file, as used by [Configurator](newbs_building_firmware_configurator.md), and `qmk compile`. You can define these macros in a list under the `macros` keyword, like this:
+
+```json
+{
+ "keyboard": "handwired/my_macropad",
+ "keymap": "my_keymap",
+ "macros": [
+ [
+ {"action":"down", "keycodes": ["LSFT"]},
+ "hello world1",
+ {"action": "up","keycodes": ["LSFT"]}
+ ],
+ [
+ {"action":"tap", "keycodes": ["LCTL", "LALT", "DEL"]}
+ ],
+ [
+ "ding!",
+ {"action":"beep"}
+ ],
+ [
+ {"action":"tap", "keycodes": ["F1"]},
+ {"action":"delay", "duration": "1000"},
+ {"action":"tap", "keycodes": ["PGDN"]}
+ ]
+ ],
+ "layout": "LAYOUT_all",
+ "layers": [
+ ["MACRO_0", "MACRO_1", "MACRO_2", "MACRO_3"]
+ ]
+}
+```
+
+### Selecting Your Host Keyboard Layout
+
+If you type in a language other than English, or use a non-QWERTY layout like Colemak, Dvorak, or Workman, you may have set your computer's input language to match this layout. This presents a challenge when creating macros - you may need to type different keys to get the same letters! To address this you can add the `host_language` key to your `keymap.json`, like so:
+
+```json
+{
+ "keyboard": "handwired/my_macropad",
+ "keymap": "my_keymap",
+ "host_language": "dvorak",
+ "macros": [
+ ["Hello, World!"]
+ ],
+ "layout": "LAYOUT_all",
+ "layers": [
+ ["MACRO_0"]
+ ]
+}
+```
+
+The current list of available languages is:
+
+| belgian | bepo | br_abnt2 | canadian_multilingual |
+|:-------:|:----:|:--------:|:---------------------:|
+| **colemak** | **croatian** | **czech** | **danish** |
+| **dvorak_fr** | **dvorak** | **dvp** | **estonian** |
+| **finnish** | **fr_ch** | **french_afnor** | **french** |
+| **french_osx** | **german_ch** | **german** | **german_osx** |
+| **hungarian** | **icelandic** | **italian** | **italian_osx_ansi** |
+| **italian_osx_iso** | **jis** | **latvian** | **lithuanian_azerty** |
+| **lithuanian_qwerty** | **norman** | **norwegian** | **portuguese** |
+| **portuguese_osx_iso** | **romanian** | **serbian_latin** | **slovak** |
+| **slovenian** | **spanish_dvorak** | **spanish** | **swedish** |
+| **turkish_f** | **turkish_q** | **uk** | **us_international** |
+| **workman** | **workman_zxcvm** |
+
+### Macro Basics
+
+Each macro is an array consisting of strings and objects (dictionaries). Strings are typed to your computer while objects allow you to control how your macro is typed out.
+
+#### Object Format
+
+All objects have one required key: `action`. This tells QMK what the object does. There are currently 5 actions: beep, delay, down, tap, up
+
+Only basic keycodes (prefixed by `KC_`) are supported. Do not include the `KC_` prefix when listing keycodes.
+
+* `beep`
+ * Play a bell if the keyboard has [audio enabled](feature_audio.md).
+ * Example: `{"action": "beep"}`
+* `delay`
+ * Pause macro playback. Duration is specified in milliseconds (ms).
+ * Example: `{"action": "delay", "duration": 500}`
+* `down`
+ * Send a key down event for one or more keycodes.
+ * Example, single key: `{"action":"down", "keycodes": ["LSFT"]}`
+ * Example, multiple keys: `{"action":"down", "keycodes": ["CTRL", "LSFT"]}`
+* `tap`
+ * Type a chord, which sends a down event for each key followed by an up event for each key.
+ * Example, single key: `{"action":"tap", "keycodes": ["F13"]}`
+ * Example, multiple keys: `{"action":"tap", "keycodes": ["CTRL", "LALT", "DEL"]}`
+* `up`
+ * Send a key up event for one or more keycodes.
+ * Example, single key: `{"action":"up", "keycodes": ["LSFT"]}`
+ * Example, multiple keys: `{"action":"up", "keycodes": ["CTRL", "LSFT"]}`
+
+## Using Macros in C Keymaps
+
+### `SEND_STRING()` & `process_record_user`
Sometimes you want a key to type out words or phrases. For the most common situations, we've provided `SEND_STRING()`, which will type out a string (i.e. a sequence of characters) for you. All ASCII characters that are easily translatable to a keycode are supported (e.g. `qmk 123\n\t`).
@@ -44,6 +144,8 @@ If yes, we send the string `"QMK is the best thing ever!"` to the computer via t
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.
+?>It is recommended to use the SAFE_RANGE macro as per [Customizing Functionality](custom_quantum_functions.md).
+
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:
@@ -91,7 +193,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
```
-### Advanced Macros
+?> An enumerated list of custom keycodes (`enum custom_keycodes`) must be declared before `keymaps[]` array, `process_record_user()` and any other function that use the list for the compiler to recognise it.
+
+#### Advanced Macros
In addition to the `process_record_user()` function, is the `post_process_record_user()` function. This runs after `process_record` and can be used to do things after a keystroke has been sent. This is useful if you want to have a key pressed before and released after a normal key, for instance.
@@ -118,7 +222,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_A ... KC_F21: //notice how it skips over F22
- case KC_F23 ... KC_EXSEL: //exsel is the last one before the modifier keys
+ case KC_F23 ... KC_EXSL: //exsel is the last one before the modifier keys
if (!record->event.pressed) {
f22_tracker--;
if (!f22_tracker) {
@@ -131,7 +235,7 @@ void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
```
-### TAP, DOWN and UP
+#### 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:
@@ -178,7 +282,7 @@ They can be used like this:
Which would send Left Control+`a` (Left Control down, `a`, Left Control up) - notice that they take strings (eg `"k"`), and not the `X_K` keycodes.
-### Alternative Keymaps
+#### 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:
@@ -186,7 +290,7 @@ By default, it assumes a US keymap with a QWERTY layout; if you want to change t
#include "sendstring_colemak.h"
```
-### Strings in Memory
+#### 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:
@@ -205,13 +309,13 @@ SEND_STRING(".."SS_TAP(X_END));
```
-## Advanced Macro Functions
+### 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.
?> You can also use the functions described in [Useful function](ref_functions.md) and [Checking modifier state](feature_advanced_keycodes#checking-modifier-state) for additional functionality. For example, `reset_keyboard()` allows you to reset the keyboard as part of a macro and `get_mods() & MOD_MASK_SHIFT` lets you check for the existence of active shift modifiers.
-### `record->event.pressed`
+#### `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
@@ -223,15 +327,15 @@ This is a boolean value that can be tested to see if the switch is being pressed
}
```
-### `register_code();`
+#### `register_code();`
This sends the `` 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();`
+#### `unregister_code();`
Parallel to `register_code` function, this sends the `` keyup event to the computer. If you don't use this, the key will be held down until it's sent.
-### `tap_code();`
+#### `tap_code();`
Sends `register_code()` and then `unregister_code()`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it).
@@ -239,31 +343,31 @@ If `TAP_CODE_DELAY` is defined (default 0), this function waits that many millis
If the keycode is `KC_CAPS`, it waits `TAP_HOLD_CAPS_DELAY` milliseconds instead (default 80), as macOS prevents accidental Caps Lock activation by waiting for the key to be held for a certain amount of time.
-### `tap_code_delay(, );`
+#### `tap_code_delay(, );`
Like `tap_code()`, but with a `delay` parameter for specifying arbitrary intervals before sending the unregister event.
-### `register_code16();`, `unregister_code16();` and `tap_code16();`
+#### `register_code16();`, `unregister_code16();` and `tap_code16();`
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();`
+#### `clear_keyboard();`
This will clear all mods and keys currently pressed.
-### `clear_mods();`
+#### `clear_mods();`
This will clear all mods currently pressed.
-### `clear_keyboard_but_mods();`
+#### `clear_keyboard_but_mods();`
This will clear all keys besides the mods currently pressed.
-## Advanced Example:
+### Advanced Example:
-### Super ALT↯TAB
+#### Super ALT↯TAB
This macro will register `KC_LALT` and tap `KC_TAB`, then wait for 1000ms. If the key is tapped again, it will send another `KC_TAB`; if there is no tap, `KC_LALT` will be unregistered, thus allowing you to cycle through windows.
diff --git a/docs/feature_midi.md b/docs/feature_midi.md
index ab29d89db6d..3da5c4940a3 100644
--- a/docs/feature_midi.md
+++ b/docs/feature_midi.md
@@ -4,7 +4,7 @@
First, enable MIDI by adding the following to your `rules.mk`:
-```makefile
+```make
MIDI_ENABLE = yes
```
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index a0d02416f28..477c20b0df5 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -56,13 +56,13 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|Define |Default|Description |
|----------------------------|-------|---------------------------------------------------------|
-|`MOUSEKEY_DELAY` |300 |Delay between pressing a movement key and cursor movement|
-|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements in milliseconds |
-|`MOUSEKEY_MOVE_DELTA` |5 |Step size |
+|`MOUSEKEY_DELAY` |10 |Delay between pressing a movement key and cursor movement|
+|`MOUSEKEY_INTERVAL` |20 |Time between cursor movements in milliseconds |
+|`MOUSEKEY_MOVE_DELTA` |8 |Step size |
|`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops |
-|`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached |
-|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement |
-|`MOUSEKEY_WHEEL_INTERVAL` |100 |Time between wheel movements |
+|`MOUSEKEY_TIME_TO_MAX` |30 |Time until maximum cursor speed is reached |
+|`MOUSEKEY_WHEEL_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
+|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements |
|`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached |
@@ -82,9 +82,9 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
|Define |Default |Description |
|--------------------------------------|---------|---------------------------------------------------------------|
|`MK_KINETIC_SPEED` |undefined|Enable kinetic mode |
-|`MOUSEKEY_DELAY` |8 |Delay between pressing a movement key and cursor movement |
-|`MOUSEKEY_INTERVAL` |8 |Time between cursor movements in milliseconds |
-|`MOUSEKEY_MOVE_DELTA` |25 |Step size for accelerating from initial to base speed |
+|`MOUSEKEY_DELAY` |5 |Delay between pressing a movement key and cursor movement |
+|`MOUSEKEY_INTERVAL` |10 |Time between cursor movements in milliseconds |
+|`MOUSEKEY_MOVE_DELTA` |5 |Step size for accelerating from initial to base speed |
|`MOUSEKEY_INITIAL_SPEED` |100 |Initial speed of the cursor in pixel per second |
|`MOUSEKEY_BASE_SPEED` |1000 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_DECELERATED_SPEED` |400 |Decelerated cursor speed |
@@ -161,7 +161,7 @@ small and detailed movements of the cursor.
* **KC_ACL2:** This acceleration sets your cursor to the maximum (computer defined) speed. This is
useful for moving the cursor large distances without much accuracy.
-To use constant speed mode, you must at least define `MK_COMBINED` in your keymap’s `config.h` file:
+To use combined speed mode, you must at least define `MK_COMBINED` in your keymap’s `config.h` file:
```c
#define MK_COMBINED
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index 49a3f0b3e36..0d04f007f8b 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -18,7 +18,7 @@ Hardware configurations using Arm-based microcontrollers or different sizes of O
## Usage
-To enable the OLED feature, there are three steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`:
+To enable the OLED feature, there are two steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`:
```make
OLED_ENABLE = yes
@@ -38,7 +38,7 @@ Then in your `keymap.c` file, implement the OLED task call. This example assumes
```c
#ifdef OLED_ENABLE
-void oled_task_user(void) {
+bool oled_task_user(void) {
// Host Keyboard Layer Status
oled_write_P(PSTR("Layer: "), false);
@@ -62,6 +62,8 @@ void oled_task_user(void) {
oled_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
oled_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
oled_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
+
+ return false;
}
#endif
```
@@ -82,6 +84,8 @@ static void render_logo(void) {
}
```
+?> The default font file is located at `drivers/oled/glcdfont.c` and its location can be overwritten with the `OLED_FONT_H` configuration option. Font file content can be edited with external tools such as [Helix Font Editor](https://helixfonteditor.netlify.app/) and [Logo Editor](https://joric.github.io/qle/).
+
## Buffer Read Example
For some purposes, you may need to read the current state of the OLED display
buffer. The `oled_read_raw` function can be used to safely read bytes from the
@@ -133,19 +137,25 @@ oled_rotation_t oled_init_user(oled_rotation_t rotation) {
return rotation;
}
-void oled_task_user(void) {
+bool oled_task_user(void) {
if (is_keyboard_master()) {
render_status(); // Renders the current keyboard state (layer, lock, caps, scroll, etc)
} else {
render_logo(); // Renders a static logo
oled_scroll_left(); // Turns on scrolling
}
+ return false;
}
#endif
```
## Basic Configuration
+These configuration options should be placed in `config.h`. Example:
+```c
+#define OLED_BRIGHTNESS 128
+```
+
|Define |Default |Description |
|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
|`OLED_DISPLAY_ADDRESS` |`0x3C` |The i2c address of the OLED Display |
@@ -154,7 +164,7 @@ void oled_task_user(void) {
|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
|`OLED_FONT_WIDTH` |`6` |The font width |
|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
-|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of keyboard inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
+|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|`OLED_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
@@ -237,6 +247,7 @@ bool oled_init(oled_rotation_t rotation);
// Called at the start of oled_init, weak function overridable by the user
// rotation - the value passed into oled_init
// Return new oled_rotation_t if you want to override default rotation
+oled_rotation_t oled_init_kb(oled_rotation_t rotation);
oled_rotation_t oled_init_user(oled_rotation_t rotation);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
@@ -328,7 +339,8 @@ uint8_t oled_get_brightness(void);
void oled_task(void);
// Called at the start of oled_task, weak function overridable by the user
-void oled_task_user(void);
+bool oled_task_kb(void);
+bool oled_task_user(void);
// Set the specific 8 lines rows of the screen to scroll.
// 0 is the default for start, and 7 for end, which is the entire
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index 37edac5e6bf..9f759ddd94f 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -1,19 +1,271 @@
# Pointing Device :id=pointing-device
-Pointing Device is a generic name for a feature intended to be generic: moving the system pointer around. There are certainly other options for it - like mousekeys - but this aims to be easily modifiable and lightweight. You can implement custom keys to control functionality, or you can gather information from other peripherals and insert it directly here - let QMK handle the processing for you.
+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 hardware driven. 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:
+To enable Pointing Device, add the following line in your rules.mk and specify one of the driver options below.
-```makefile
+```make
POINTING_DEVICE_ENABLE = yes
```
-To manipulate the mouse report, you can use the following functions:
+## Sensor Drivers
-* `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
+There are a number of sensors that are supported by default. Note that only one sensor can be enabled by `POINTING_DEVICE_DRIVER` at a time. If you need to enable more than one sensor, then you need to implement it manually.
+
+### ADNS 5050 Sensor
+
+To use the ADNS 5050 sensor, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = adns5050
+```
+
+The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.
+
+| Setting | Description |
+|--------------------|---------------------------------------------------------------------|
+|`ADNS5050_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. |
+|`ADNS5050_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. |
+|`ADNS5050_CS_PIN` | (Required) The pin connected to the cable select pin of the sensor. |
+
+The CPI range is 125-1375, in increments of 125. Defaults to 500 CPI.
+
+### ADNS 9800 Sensor
+
+To use the ADNS 9800 sensor, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = adns9800
+```
+
+The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.
+
+| Setting | Description | Default |
+|--------------------------------|------------------------------------------------------------------------|---------------|
+|`ADNS9800_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`ADNS9800_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`ADNS9800_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`ADNS9800_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+
+
+The CPI range is 800-8200, in increments of 200. Defaults to 1800 CPI.
+
+### Analog Joystick
+
+To use an analog joystick to control the pointer, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = analog_joystick
+```
+
+The Analog Joystick is an analog (ADC) driven sensor. There are a variety of joysticks that you can use for this.
+
+| Setting | Description | Default |
+|----------------------------------|----------------------------------------------------------------------------|---------------|
+|`ANALOG_JOYSTICK_X_AXIS_PIN` | (Required) The pin used for the vertical/X axis. | _not defined_ |
+|`ANALOG_JOYSTICK_Y_AXIS_PIN` | (Required) The pin used for the horizontal/Y axis. | _not defined_ |
+|`ANALOG_JOYSTICK_AXIS_MIN` | (Optional) Sets the lower range to be considered movement. | `0` |
+|`ANALOG_JOYSTICK_AXIS_MAX` | (Optional) Sets the upper range to be considered movement. | `1023` |
+|`ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20` |
+|`ANALOG_JOYSTICK_READ_INTERVAL` | (Optional) The interval in milliseconds between reads. | `10` |
+|`ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` |
+|`ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
+
+
+### Cirque Trackpad
+
+To use the Cirque Trackpad sensor, add this to your `rules.mk`:
+
+```make
+POINTING_DEVICE_DRIVER = cirque_pinnacle_i2c
+```
+
+or
+
+```make
+POINTING_DEVICE_DRIVER = cirque_pinnacle_spi
+```
+
+
+This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported.
+
+| Setting | Description | Default |
+|---------------------------------|---------------------------------------------------------------------------------|-----------------------|
+|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` |
+|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` |
+|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` |
+|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` |
+|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
+|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
+
+| I2C Setting | Description | Default |
+|--------------------------|---------------------------------------------------------------------------------|---------|
+|`CIRQUE_PINNACLE_ADDR` | (Required) Sets the I2C Address for the Cirque Trackpad | `0x2A` |
+|`CIRQUE_PINNACLE_TIMEOUT` | (Optional) The timeout for i2c communication with the trackpad in milliseconds. | `20` |
+
+| SPI Setting | Description | Default |
+|-------------------------------|------------------------------------------------------------------------|---------------|
+|`CIRQUE_PINNACLE_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `1000000` |
+|`CIRQUE_PINNACLE_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`CIRQUE_PINNACLE_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `1` |
+|`CIRQUE_PINNACLE_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`CIRQUE_PINNACLE_SPI_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+
+Default Scaling/CPI is 1024.
+
+### Pimoroni Trackball
+
+To use the Pimoroni Trackball module, add this to your `rules.mk`:
+
+```make
+POINTING_DEVICE_DRIVER = pimoroni_trackball
+```
+
+The Pimoroni Trackball module is a I2C based breakout board with an RGB enable trackball.
+
+| Setting | Description | Default |
+|-------------------------------------|------------------------------------------------------------------------------------|---------|
+|`PIMORONI_TRACKBALL_ADDRESS` | (Required) Sets the I2C Address for the Pimoroni Trackball. | `0x0A` |
+|`PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackball in milliseconds. | `100` |
+|`PIMORONI_TRACKBALL_SCALE` | (Optional) The multiplier used to generate reports from the sensor. | `5` |
+|`PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` |
+|`PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
+
+### PMW 3360 Sensor
+
+To use the PMW 3360 sensor, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = pmw3360
+```
+
+The PMW 3360 is an SPI driven optical sensor, that uses a built in IR LED for surface tracking.
+
+| Setting | Description | Default |
+|-----------------------------|--------------------------------------------------------------------------------------------|---------------|
+|`PMW3360_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+|`PMW3360_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`PMW3360_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`PMW3360_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`PMW3360_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`PMW3360_LIFTOFF_DISTANCE` | (Optional) Sets the lift off distance at run time | `0x02` |
+|`ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 127 degrees directly in the sensor.| `0` |
+|`PMW3360_FIRMWARE_UPLOAD_FAST` | (Optional) Skips the 15us wait between firmware blocks. | _not defined_ |
+
+The CPI range is 100-12000, in increments of 100. Defaults to 1600 CPI.
+
+### PMW 3389 Sensor
+
+To use the PMW 3389 sensor, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = pmw3389
+```
+
+The PMW 3389 is an SPI driven optical sensor, that uses a built in IR LED for surface tracking.
+
+| Setting | Description | Default |
+|---------------------------------|--------------------------------------------------------------------------------------------|---------------|
+|`PMW3389_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+|`PMW3389_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`PMW3389_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`PMW3389_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`PMW3389_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`PMW3389_LIFTOFF_DISTANCE` | (Optional) Sets the lift off distance at run time | `0x02` |
+|`ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 30 degrees directly in the sensor. | `0` |
+|`PMW3389_FIRMWARE_UPLOAD_FAST` | (Optional) Skips the 15us wait between firmware blocks. | _not defined_ |
+
+The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.
+
+
+### Custom Driver
-Keep in mind that a report_mouse_t (here "mouseReport") has the following properties:
+If you have a sensor type that isn't supported above, a custom option is available by adding the following to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = custom
+```
+
+Using the custom driver will require implementing the following functions:
+
+```c
+void pointing_device_driver_init(void) {}
+report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; }
+uint16_t pointing_device_driver_get_cpi(void) { return 0; }
+void pointing_device_driver_set_cpi(uint16_t cpi) {}
+```
+
+!> Ideally, new sensor hardware should be added to `drivers/sensors/` and `quantum/pointing_device_drivers.c`, but there may be cases where it's very specific to the hardware. So these functions are provided, just in case.
+
+## Common Configuration
+
+| Setting | Description | Default |
+|----------------------------------|-----------------------------------------------------------------------|-------------------|
+|`POINTING_DEVICE_ROTATION_90` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
+|`POINTING_DEVICE_ROTATION_180` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
+|`POINTING_DEVICE_ROTATION_270` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
+|`POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ |
+|`POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ |
+|`POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ |
+|`POINTING_DEVICE_TASK_THROTTLE_MS` | (Optional) Limits the frequency that the sensor is polled for motion. | _not defined_ |
+
+!> When using `SPLIT_POINTING_ENABLE` the `POINTING_DEVICE_MOTION_PIN` functionality is not supported and `POINTING_DEVICE_TASK_THROTTLE_MS` will default to `1`. Increasing this value will increase transport performance at the cost of possible mouse responsiveness.
+
+
+## Split Keyboard Configuration
+
+The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](feature_split_keyboard.md?id=data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device.
+
+| Setting | Description | Default |
+|----------------------------------------|-----------------------------------------------------------------------|---------------|
+|`POINTING_DEVICE_LEFT` | Pointing device on the left side (Required - pick one only) | _not defined_ |
+|`POINTING_DEVICE_RIGHT` | Pointing device on the right side (Required - pick one only) | _not defined_ |
+|`POINTING_DEVICE_COMBINED` | Pointing device on both sides (Required - pick one only) | _not defined_ |
+|`POINTING_DEVICE_ROTATION_90_RIGHT` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
+|`POINTING_DEVICE_ROTATION_180_RIGHT` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
+|`POINTING_DEVICE_ROTATION_270_RIGHT` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
+|`POINTING_DEVICE_INVERT_X_RIGHT` | (Optional) Inverts the X axis report. | _not defined_ |
+|`POINTING_DEVICE_INVERT_Y_RIGHT` | (Optional) Inverts the Y axis report. | _not defined_ |
+
+!> If there is a `_RIGHT` configuration option or callback, the [common configuration](feature_pointing_device.md?id=common-configuration) option will work for the left. For correct left/right detection you should setup a [handedness option](feature_split_keyboard?id=setting-handedness), `EE_HANDS` is usually a good option for an existing board that doesn't do handedness by hardware.
+
+
+## Callbacks and Functions
+
+| Function | Description |
+|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
+| `pointing_device_init_kb(void)` | Callback to allow for keyboard level initialization. Useful for additional hardware sensors. |
+| `pointing_device_init_user(void)` | Callback to allow for user level initialization. Useful for additional hardware sensors. |
+| `pointing_device_task_kb(mouse_report)` | Callback that sends sensor data, so keyboard code can intercept and modify the data. Returns a mouse report. |
+| `pointing_device_task_user(mouse_report)` | Callback that sends sensor data, so user code can intercept and modify the data. Returns a mouse report. |
+| `pointing_device_handle_buttons(buttons, pressed, button)` | Callback to handle hardware button presses. Returns a `uint8_t`. |
+| `pointing_device_get_cpi(void)` | Gets the current CPI/DPI setting from the sensor, if supported. |
+| `pointing_device_set_cpi(uint16_t)` | Sets the CPI/DPI, if supported. |
+| `pointing_device_get_report(void)` | Returns the current mouse report (as a `mouse_report_t` data structure). |
+| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `mouse_report_t` data structured passed to the function. |
+| `pointing_device_send(void)` | Sends the current mouse report to the host system. Function can be replaced. |
+| `has_mouse_report_changed(old, new)` | Compares the old and new `mouse_report_t` data and returns true only if it has changed. |
+| `pointing_device_adjust_by_defines(mouse_report)` | Applies rotations and invert configurations to a raw mouse report. |
+
+
+## Split Keyboard Callbacks and Functions
+
+The combined functions below are only available when using `SPLIT_POINTING_ENABLE` and `POINTING_DEVICE_COMBINED`. The 2 callbacks `pointing_device_task_combined_*` replace the single sided equivalents above. See the [combined pointing devices example](feature_pointing_device.md?id=combined-pointing-devices)
+
+| Function | Description |
+|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
+| `pointing_device_set_shared_report(mouse_report)` | Sets the shared mouse report to the assigned `mouse_report_t` data structured passed to the function. |
+| `pointing_device_set_cpi_on_side(bool, uint16_t)` | Sets the CPI/DPI of one side, if supported. Passing `true` will set the left and `false` the right` |
+| `pointing_device_combine_reports(left_report, right_report)` | Returns a combined mouse_report of left_report and right_report (as a `mouse_report_t` data structure) |
+| `pointing_device_task_combined_kb(left_report, right_report)` | Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report. |
+| `pointing_device_task_combined_user(left_report, right_report)` | Callback, so user code can intercept and modify. Returns a combined mouse report using `pointing_device_combine_reports` |
+| `pointing_device_adjust_by_defines_right(mouse_report)` | Applies right side rotations and invert configurations to a raw mouse report. |
+
+
+# Manipulating Mouse Reports
+
+The 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.
@@ -21,8 +273,10 @@ Keep in mind that a report_mouse_t (here "mouseReport") has the following proper
* `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.
-Once you have made the necessary changes to the mouse report, you need to send it:
+To manually manipulate the mouse reports outside of the `pointing_device_task_*` functions, you can use:
+* `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
* `pointing_device_send()` - Sends the mouse report to the host and zeroes out the report.
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.
@@ -31,7 +285,11 @@ Additionally, by default, `pointing_device_send()` will only send a report when
Also, you use the `has_mouse_report_changed(new, old)` function to check to see if the report has changed.
-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:
+## Examples
+
+### Custom Mouse Keycode
+
+In this 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.
```c
case MS_SPECIAL:
@@ -51,3 +309,92 @@ case MS_SPECIAL:
```
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.
+
+### Drag Scroll or Mouse Scroll
+
+A very common implementation is to use the mouse movement to scroll instead of moving the cursor on the system. This uses the `pointing_device_task_user` callback to intercept and modify the mouse report before it's sent to the host system.
+
+```c
+enum custom_keycodes {
+ DRAG_SCROLL = SAFE_RANGE,
+};
+
+bool set_scrolling = false;
+
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
+ if (set_scrolling) {
+ mouse_report.h = mouse_report.x;
+ mouse_report.v = mouse_report.y;
+ mouse_report.x = mouse_report.y = 0
+ }
+ return mouse_report;
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ if (keycode == DRAG_SCROLL && record->event.pressed) {
+ set_scrolling = !set_scrolling;
+ }
+ return true;
+}
+```
+
+This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.
+
+## Split Examples
+
+The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
+
+### Single Pointing Device
+
+The following example will work with either `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` and enables scrolling mode while on a particular layer.
+
+```c
+
+static bool scrolling_mode = false;
+
+layer_state_t layer_state_set_user(layer_state_t state) {
+ switch (get_highest_layer(state)) {
+ case _RAISE: // If we're on the _RAISE layer enable scrolling mode
+ scrolling_mode = true;
+ pointing_device_set_cpi(2000);
+ break;
+ default:
+ if (scrolling_mode) { // check if we were scrolling before and set disable if so
+ scrolling_mode = false;
+ pointing_device_set_cpi(8000);
+ }
+ break;
+ }
+ return state;
+}
+
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
+ if (scrolling_mode) {
+ mouse_report.h = mouse_report.x;
+ mouse_report.v = mouse_report.y;
+ mouse_report.x = 0;
+ mouse_report.y = 0;
+ }
+ return mouse_report;
+}
+```
+
+### Combined Pointing Devices
+
+The following example requires `POINTING_DEVICE_COMBINED` and sets the left side pointing device to scroll only.
+
+```c
+void keyboard_post_init_user(void) {
+ pointing_device_set_cpi_on_side(true, 1000); //Set cpi on left side to a low value for slower scrolling.
+ pointing_device_set_cpi_on_side(false, 8000); //Set cpi on right side to a reasonable value for mousing.
+}
+
+report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
+ left_report.h = left_report.x;
+ left_report.v = left_report.y;
+ left_report.x = 0;
+ left_report.y = 0;
+ return pointing_device_combine_reports(left_report, right_report);
+}
+```
+=======
diff --git a/docs/feature_programmable_button.md b/docs/feature_programmable_button.md
new file mode 100644
index 00000000000..b1ef555d16a
--- /dev/null
+++ b/docs/feature_programmable_button.md
@@ -0,0 +1,74 @@
+## Programmable Button
+
+Programmable button is a feature that can be used to send keys that have no
+predefined meaning.
+This means they can be processed on the host side by custom software without
+colliding without the operating system trying to interpret these keys.
+
+The keycodes are emitted according to the HID usage
+"Telephony Device Page" (0x0B), "Programmable button usage" (0x07).
+On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#`
+keycodes.
+(Up to `KEY_MACRO30`)
+
+### Enabling Programmable Button support
+
+To enable Programmable Button, add the following line to your keymap’s `rules.mk`:
+
+```c
+PROGRAMMABLE_BUTTON_ENABLE = yes
+```
+
+### Mapping
+
+In your keymap you can use the following keycodes to map key presses to Programmable Buttons:
+
+|Key |Description |
+|------------------------|----------------------|
+|`PROGRAMMABLE_BUTTON_1` |Programmable button 1 |
+|`PROGRAMMABLE_BUTTON_2` |Programmable button 2 |
+|`PROGRAMMABLE_BUTTON_3` |Programmable button 3 |
+|`PROGRAMMABLE_BUTTON_4` |Programmable button 4 |
+|`PROGRAMMABLE_BUTTON_5` |Programmable button 5 |
+|`PROGRAMMABLE_BUTTON_6` |Programmable button 6 |
+|`PROGRAMMABLE_BUTTON_7` |Programmable button 7 |
+|`PROGRAMMABLE_BUTTON_8` |Programmable button 8 |
+|`PROGRAMMABLE_BUTTON_9` |Programmable button 9 |
+|`PROGRAMMABLE_BUTTON_10`|Programmable button 10|
+|`PROGRAMMABLE_BUTTON_11`|Programmable button 11|
+|`PROGRAMMABLE_BUTTON_12`|Programmable button 12|
+|`PROGRAMMABLE_BUTTON_13`|Programmable button 13|
+|`PROGRAMMABLE_BUTTON_14`|Programmable button 14|
+|`PROGRAMMABLE_BUTTON_15`|Programmable button 15|
+|`PROGRAMMABLE_BUTTON_16`|Programmable button 16|
+|`PROGRAMMABLE_BUTTON_17`|Programmable button 17|
+|`PROGRAMMABLE_BUTTON_18`|Programmable button 18|
+|`PROGRAMMABLE_BUTTON_19`|Programmable button 19|
+|`PROGRAMMABLE_BUTTON_20`|Programmable button 20|
+|`PROGRAMMABLE_BUTTON_21`|Programmable button 21|
+|`PROGRAMMABLE_BUTTON_22`|Programmable button 22|
+|`PROGRAMMABLE_BUTTON_23`|Programmable button 23|
+|`PROGRAMMABLE_BUTTON_24`|Programmable button 24|
+|`PROGRAMMABLE_BUTTON_25`|Programmable button 25|
+|`PROGRAMMABLE_BUTTON_26`|Programmable button 26|
+|`PROGRAMMABLE_BUTTON_27`|Programmable button 27|
+|`PROGRAMMABLE_BUTTON_28`|Programmable button 28|
+|`PROGRAMMABLE_BUTTON_29`|Programmable button 29|
+|`PROGRAMMABLE_BUTTON_30`|Programmable button 30|
+|`PROGRAMMABLE_BUTTON_31`|Programmable button 31|
+|`PROGRAMMABLE_BUTTON_32`|Programmable button 32|
+|`PB_1` to `PB_32` |Aliases for keymaps |
+
+### API
+
+You can also use a dedicated API defined in `programmable_button.h` to interact with this feature:
+
+```
+void programmable_button_clear(void);
+void programmable_button_send(void);
+void programmable_button_on(uint8_t code);
+void programmable_button_off(uint8_t code);
+bool programmable_button_is_on(uint8_t code);
+uint32_t programmable_button_get_report(void);
+void programmable_button_set_report(uint32_t report);
+```
diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md
index 776a33150ec..c980705ae7f 100644
--- a/docs/feature_ps2_mouse.md
+++ b/docs/feature_ps2_mouse.md
@@ -30,7 +30,7 @@ Note: This is not recommended, you may encounter jerky movement or unsent inputs
In rules.mk:
-```makefile
+```make
PS2_MOUSE_ENABLE = yes
PS2_USE_BUSYWAIT = yes
```
@@ -39,14 +39,8 @@ In your keyboard config.h:
```c
#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
+# define PS2_CLOCK_PIN D1
+# define PS2_DATA_PIN D2
#endif
```
@@ -56,7 +50,7 @@ The following example uses D2 for clock and D5 for data. You can use any INT or
In rules.mk:
-```makefile
+```make
PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes
```
@@ -65,14 +59,8 @@ In your keyboard config.h:
```c
#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_CLOCK_PIN D2
+#define PS2_DATA_PIN D5
#define PS2_INT_INIT() do { \
EICRA |= ((1<` de
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `ISSI_3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
@@ -49,10 +50,12 @@ Here is an example using 2 drivers.
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
+For split keyboards using `RGB_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `DRIVER_ADDR_1` for one and `DRIVER_ADDR_2` for the other one. Then, in `g_is31_leds`, fill out the correct driver index (0 or 1). If using one address, use `DRIVER_ADDR_1` for both, and use index 0 for `g_is31_leds`.
+
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -71,7 +74,7 @@ Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet]
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
-```makefile
+```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3733
```
@@ -82,6 +85,9 @@ You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_` de
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
+| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
+| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
@@ -93,6 +99,18 @@ You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_` de
| `DRIVER_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 |
| `DRIVER_SYNC_4` | (Optional) Sync configuration for the fourth RGB driver | 0 |
+The IS31FL3733 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
+
+| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
+|----------------------|-------------|
+| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
+| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
+| `PUR_3KR` | The 3k Ohm resistor used at all times |
+| `PUR_4KR` | The 4k Ohm resistor used at all times |
+| `PUR_8KR` | The 8k Ohm resistor used at all times |
+| `PUR_16KR` | The 16k Ohm resistor used at all times |
+| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
+
Here is an example using 2 drivers.
```c
@@ -122,7 +140,7 @@ Currently only 4 drivers are supported, but it would be trivial to support all 8
Define these arrays listing all the LEDs in your `.c`:
```c
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -141,7 +159,7 @@ Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3737 RGB controller. To enable it, add this to your `rules.mk`:
-```makefile
+```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3737
```
@@ -153,11 +171,25 @@ Configure the hardware via your `config.h`:
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
+| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
+The IS31FL3737 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
+
+| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
+|----------------------|-------------|
+| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
+| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
+| `PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
+| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
+| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
+| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
+| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
+| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
@@ -181,12 +213,12 @@ Here is an example using 2 drivers.
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
-Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
+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 `.c`:
```c
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -200,13 +232,122 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1` for now).
+---
+### IS31FLCOMMON :id=is31flcommon
+
+There is basic support for addressable RGB matrix lighting with a selection of I2C ISSI Lumissil RGB controllers through a shared common driver. To enable it, add this to your `rules.mk`:
+
+```makefile
+RGB_MATRIX_ENABLE = yes
+RGB_MATRIX_DRIVER =
+```
+
+Where `` is the applicable LED driver chip as below
+
+| Driver Name | Data Sheet | Capability |
+|-------------|------------|------------|
+| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 60 RGB, 30x6 Matrix |
+| `ISSIFL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 66 RGB, 18x11 Matrix |
+| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 48 RGB, 18x8 Matrix |
+| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 24 RGB, 18x4 Matrix |
+
+You can use between 1 and 4 IC's. Do not specify `DRIVER_ADDR_` define for IC's if not present on your keyboard. The `DRIVER_ADDR_1` default assumes that all Address pins on the controller have been connected to GND. Drivers that have SYNC functionality have the default settings to disable if 1 driver. If more than 1 drivers then `DRIVER_ADDR_1` will be set to Master and the remaining ones set to Slave.
+
+Configure the hardware via your `config.h`:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
+| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
+| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
+| `DRIVER_ADDR_1` | (Optional) Address for the first RGB driver | |
+| `DRIVER_ADDR_` | (Required) Address for the additional RGB drivers | |
+| `ISSI_SSR_` | (Optional) Configuration for the Spread Spectrum Register | |
+| `ISSI_CONFIGURATION` | (Optional) Configuration for the Configuration Register | |
+| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
+| `ISSI_PULLDOWNUP` | (Optional) Configuration for the Pull Up & Pull Down Register | |
+| `ISSI_TEMP` | (Optional) Configuration for the Tempature Register | |
+| `ISSI_PWM_ENABLE` | (Optional) Configuration for the PWM Enable Register | |
+| `ISSI_PWM_SET` | (Optional) Configuration for the PWM Setting Register | |
+| `ISSI_SCAL_RED` | (Optional) Configuration for the RED LEDs in Scaling Registers | 0xFF |
+| `ISSI_SCAL_BLUE` | (Optional) Configuration for the BLUE LEDs in Scaling Registers | 0xFF |
+| `ISSI_SCAL_GREEN` | (Optional) Configuration for the GREEN LEDs in Scaling Registers | 0xFF |
+| `ISSI_MANUAL_SCALING` | (Optional) If you wish to configure the Scaling Registers manually | |
+
+
+Defaults
+
+| Variable | IS31FL3742A | IS31FL3743A | IS31FL3745 | IS31FL3746 |
+|----------|-------------|-------------|------------|------------|
+| `DRIVER_ADDR_1` | 0b0110000 | 0b0100000 | 0b0100000 | 0b1100000 |
+| `ISSI_SSR_1` | 0x00 | 0x00 / 0x60 | 0x00 / 0xC0 | 0x00 |
+| `ISSI_SSR_<2-4>` | 0x00 | 0x40 | 0x80 | 0x00 |
+| `ISSI_CONFIGURATION` | 0x31 | 0x01 | 0x31 | 0x01 |
+| `ISSI_PULLDOWNUP` | 0x55 | 0x33 | 0x33 | 0x33 |
+| `ISSI_TEMP` | N/A | 0x00 | 0x00 | 0x00 |
+| `ISSI_PWM_ENABLE` | N/A | N/A | N/A | 0x00 |
+| `ISSI_PWM_SET` | 0x00 | N/A | N/A | 0x00 |
+
+Here is an example using 2 drivers.
+
+```c
+#define DRIVER_ADDR_2 0b0100001
+
+#define DRIVER_COUNT 2
+#define DRIVER_1_LED_TOTAL 66
+#define DRIVER_2_LED_TOTAL 42
+#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
+```
+
+!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
+
+Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
+
+Define these arrays listing all the LEDs in your `