mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-08-22 17:24:41 +00:00
Compare commits
214 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9813a6f950 | ||
![]() |
fadb69e203 | ||
![]() |
ee8d9bd40a | ||
![]() |
d578aaefcd | ||
![]() |
75b28225db | ||
![]() |
5d23fb1e3a | ||
![]() |
d14ef52b80 | ||
![]() |
41482e02a6 | ||
![]() |
547fbe769c | ||
![]() |
5004562441 | ||
![]() |
0ec0d29e9f | ||
![]() |
d8d2a09674 | ||
![]() |
576b138c6e | ||
![]() |
38ad0d2673 | ||
![]() |
ed65881565 | ||
![]() |
b93e1309e5 | ||
![]() |
9114d6ebe9 | ||
![]() |
c0e6734d3f | ||
![]() |
406f03bb0c | ||
![]() |
405dea01be | ||
![]() |
2f6c068e0d | ||
![]() |
2a534e87ac | ||
![]() |
f3e73965f0 | ||
![]() |
b4c03070de | ||
![]() |
4d72aa428f | ||
![]() |
57540af102 | ||
![]() |
2c0c25d014 | ||
![]() |
8479dd65d4 | ||
![]() |
3cb28bbe42 | ||
![]() |
74d7d232e3 | ||
![]() |
340c3abc28 | ||
![]() |
009d45d4d7 | ||
![]() |
59d3b37130 | ||
![]() |
a6701c28d2 | ||
![]() |
98b237a21b | ||
![]() |
07bdc8f4b7 | ||
![]() |
ae934c389e | ||
![]() |
6b27ebefc6 | ||
![]() |
f54e47c79d | ||
![]() |
9587fac72a | ||
![]() |
e5831d79c0 | ||
![]() |
d967d3a6b5 | ||
![]() |
620fcf12e8 | ||
![]() |
cacfaedb81 | ||
![]() |
209b6baaa8 | ||
![]() |
7f8922ae7b | ||
![]() |
72f382fc02 | ||
![]() |
430c37024e | ||
![]() |
f644db042c | ||
![]() |
465acd4d09 | ||
![]() |
9ae874e0c3 | ||
![]() |
0261bf3e30 | ||
![]() |
586bd92ea7 | ||
![]() |
d68d510473 | ||
![]() |
ac20e7e3f2 | ||
![]() |
a2d61d76fa | ||
![]() |
17eea779df | ||
![]() |
f1cebc9d9d | ||
![]() |
9609ae60a6 | ||
![]() |
2a9856dff0 | ||
![]() |
b567785345 | ||
![]() |
9177c6fedd | ||
![]() |
13493d3a78 | ||
![]() |
2f3807682d | ||
![]() |
4c4850f32a | ||
![]() |
48cc61b188 | ||
![]() |
45950bb3b6 | ||
![]() |
a8427447bc | ||
![]() |
046fb11259 | ||
![]() |
77a1c75cf6 | ||
![]() |
5cf7dbedd2 | ||
![]() |
f2e0d38f17 | ||
![]() |
c57994f09e | ||
![]() |
43f388166f | ||
![]() |
de107eb14e | ||
![]() |
d5ab675251 | ||
![]() |
a699fd3d04 | ||
![]() |
207ebc42a9 | ||
![]() |
b28f1e6a29 | ||
![]() |
c806103f41 | ||
![]() |
eafd38e2a1 | ||
![]() |
e5bc50c03e | ||
![]() |
1c5079a33c | ||
![]() |
c9424eb8d7 | ||
![]() |
bbdc82dd36 | ||
![]() |
ec3954577c | ||
![]() |
48067c530c | ||
![]() |
57958ce88e | ||
![]() |
dd6330b07c | ||
![]() |
cd7bc03134 | ||
![]() |
22a8992d1b | ||
![]() |
2367e3e1fd | ||
![]() |
0bd03150e5 | ||
![]() |
feddc496ee | ||
![]() |
abb65857ff | ||
![]() |
36d3902504 | ||
![]() |
f204ed67f2 | ||
![]() |
f3acaff65b | ||
![]() |
20c0533c4c | ||
![]() |
a747953dfa | ||
![]() |
1ab008eabd | ||
![]() |
0a7222b703 | ||
![]() |
4381dea621 | ||
![]() |
827f8ce1bc | ||
![]() |
207fde997f | ||
![]() |
b1691ba696 | ||
![]() |
7ec583e5ef | ||
![]() |
c966da89da | ||
![]() |
8060e52946 | ||
![]() |
2e8cdb126e | ||
![]() |
3261c408e4 | ||
![]() |
d41961c9ed | ||
![]() |
840b9090a0 | ||
![]() |
40b0ddd425 | ||
![]() |
17ff9cf554 | ||
![]() |
d3ebf903c9 | ||
![]() |
f1c89280d5 | ||
![]() |
4602361095 | ||
![]() |
28f53462d0 | ||
![]() |
4532caf5f2 | ||
![]() |
e08e6c11e3 | ||
![]() |
bffbb4b42d | ||
![]() |
d686c0ea43 | ||
![]() |
b3cdc7ef70 | ||
![]() |
cf2ffadbcd | ||
![]() |
0da743d80b | ||
![]() |
7afae46ea6 | ||
![]() |
c644299820 | ||
![]() |
a2e91ebec9 | ||
![]() |
a40dbf94e8 | ||
![]() |
1c0a7ad6c2 | ||
![]() |
6b1db7da23 | ||
![]() |
001a6c24ae | ||
![]() |
b1fc3f35c6 | ||
![]() |
e040028f1b | ||
![]() |
d417b0cc7d | ||
![]() |
b12b26946d | ||
![]() |
918fb7f8da | ||
![]() |
455f15528c | ||
![]() |
00c6892b3f | ||
![]() |
171f7c561b | ||
![]() |
5b4187ad1b | ||
![]() |
d5b01bd34b | ||
![]() |
1650ba00f1 | ||
![]() |
f9d47ebe2f | ||
![]() |
3895b4b868 | ||
![]() |
a8647f0d27 | ||
![]() |
6c7d173ad7 | ||
![]() |
65906f679d | ||
![]() |
6af77551c6 | ||
![]() |
4747d974aa | ||
![]() |
e5d2cb8f98 | ||
![]() |
f6c7e11426 | ||
![]() |
97a3f806c4 | ||
![]() |
c44fc68297 | ||
![]() |
5fa0a274ea | ||
![]() |
4e375aa1f5 | ||
![]() |
f859375284 | ||
![]() |
f6651424a0 | ||
![]() |
29e9caa82b | ||
![]() |
a32f7e1a25 | ||
![]() |
e2dfb787da | ||
![]() |
72df7b4c19 | ||
![]() |
1209fb8643 | ||
![]() |
ba42a5ae68 | ||
![]() |
09f5767072 | ||
![]() |
ed6a872911 | ||
![]() |
311d625c56 | ||
![]() |
a71c461d03 | ||
![]() |
a5ecf14608 | ||
![]() |
26bbf6a66a | ||
![]() |
f14629ed1c | ||
![]() |
2a231457bd | ||
![]() |
0f95c0865c | ||
![]() |
3538955778 | ||
![]() |
7d557a0514 | ||
![]() |
a25dd58bc5 | ||
![]() |
7ba82cb5b7 | ||
![]() |
a200f194d1 | ||
![]() |
b2fb0ceeef | ||
![]() |
ff0cb0cf9d | ||
![]() |
cbcf888dc0 | ||
![]() |
d8253b83e8 | ||
![]() |
0a03f7cff7 | ||
![]() |
21fc6be41b | ||
![]() |
989c2094f8 | ||
![]() |
fd48f687b1 | ||
![]() |
f8e4921491 | ||
![]() |
66b63f66a9 | ||
![]() |
77a7e3c91f | ||
![]() |
b8c5efa555 | ||
![]() |
4211252117 | ||
![]() |
0694decfa1 | ||
![]() |
da1f05fbc1 | ||
![]() |
cf215487ba | ||
![]() |
e717dcaa09 | ||
![]() |
38fdf7a2d2 | ||
![]() |
663ca6ba9d | ||
![]() |
37d2f6dc2a | ||
![]() |
475d2c0c30 | ||
![]() |
2121de9192 | ||
![]() |
901edea927 | ||
![]() |
8e348c427d | ||
![]() |
2bbbfc6154 | ||
![]() |
ecf0612cc8 | ||
![]() |
676633e1f3 | ||
![]() |
e6420f0bd8 | ||
![]() |
3ee062222a | ||
![]() |
3dd2905b7b | ||
![]() |
607f6f5c16 | ||
![]() |
ffff0f03cb | ||
![]() |
721b3546f6 | ||
![]() |
05a97482e6 | ||
![]() |
05990c9bda |
@@ -16,6 +16,10 @@ insert_final_newline = true
|
||||
trim_trailing_whitespace = false
|
||||
indent_size = 4
|
||||
|
||||
[{qmk,*.py}]
|
||||
charset = utf-8
|
||||
max_line_length = 200
|
||||
|
||||
# Make these match what we have in .gitattributes
|
||||
[*.mk]
|
||||
end_of_line = lf
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -70,3 +70,6 @@ util/Win_Check_Output.txt
|
||||
secrets.tar
|
||||
id_rsa_*
|
||||
/.vs
|
||||
|
||||
# python things
|
||||
__pycache__
|
||||
|
@@ -13,8 +13,6 @@ env:
|
||||
- MAKEFLAGS="-j3 --output-sync"
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
- docker build -t qmkfm/qmk_firmware .
|
||||
install:
|
||||
- npm install -g moxygen
|
||||
script:
|
||||
|
24
Dockerfile
24
Dockerfile
@@ -1,26 +1,4 @@
|
||||
FROM debian:9
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
avr-libc \
|
||||
avrdude \
|
||||
binutils-arm-none-eabi \
|
||||
binutils-avr \
|
||||
build-essential \
|
||||
dfu-programmer \
|
||||
dfu-util \
|
||||
gcc \
|
||||
gcc-avr \
|
||||
git \
|
||||
libnewlib-arm-none-eabi \
|
||||
software-properties-common \
|
||||
unzip \
|
||||
wget \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# upgrade gcc-arm-none-eabi from the default 5.4.1 to 6.3.1 due to ARM runtime issues
|
||||
RUN wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -O - | \
|
||||
tar xj --strip-components=1 -C /
|
||||
FROM qmkfm/base_container
|
||||
|
||||
VOLUME /qmk_firmware
|
||||
WORKDIR /qmk_firmware
|
||||
|
9
Makefile
9
Makefile
@@ -20,7 +20,10 @@ endif
|
||||
override SILENT := false
|
||||
|
||||
ifndef SUB_IS_SILENT
|
||||
QMK_VERSION := $(shell git describe --abbrev=0 --tags 2>/dev/null)
|
||||
ifndef SKIP_GIT
|
||||
QMK_VERSION := $(shell git describe --abbrev=0 --tags 2>/dev/null)
|
||||
endif
|
||||
|
||||
ifneq ($(QMK_VERSION),)
|
||||
$(info QMK Firmware $(QMK_VERSION))
|
||||
endif
|
||||
@@ -94,6 +97,7 @@ $(eval $(call NEXT_PATH_ELEMENT))
|
||||
# endif
|
||||
|
||||
define GET_KEYBOARDS
|
||||
ifndef ALT_GET_KEYBOARDS
|
||||
All_RULES_MK := $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/rules.mk))
|
||||
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/rules.mk))
|
||||
All_RULES_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/rules.mk))
|
||||
@@ -105,6 +109,9 @@ define GET_KEYBOARDS
|
||||
KEYMAPS_MK += $$(patsubst $(ROOT_DIR)/keyboards/%/rules.mk,%,$$(wildcard $(ROOT_DIR)/keyboards/*/*/*/*/keymaps/*/rules.mk))
|
||||
|
||||
KEYBOARDS := $$(sort $$(filter-out $$(KEYMAPS_MK), $$(All_RULES_MK)))
|
||||
else
|
||||
KEYBOARDS := $(shell find keyboards/ -type f -iname "rules.mk" | grep -v keymaps | sed 's!keyboards/\(.*\)/rules.mk!\1!' | sort | uniq)
|
||||
endif
|
||||
endef
|
||||
|
||||
$(eval $(call GET_KEYBOARDS))
|
||||
|
31
Vagrantfile
vendored
31
Vagrantfile
vendored
@@ -52,26 +52,37 @@ Vagrant.configure(2) do |config|
|
||||
end
|
||||
|
||||
# Docker provider pulls from hub.docker.com respecting docker.image if
|
||||
# config.vm.box is nil. Note that this bind-mounts from the current dir to
|
||||
# config.vm.box is nil. In this case, we adhoc build util/vagrant/Dockerfile.
|
||||
# Note that this bind-mounts from the current dir to
|
||||
# /vagrant in the guest, so unless your UID is 1000 to match vagrant in the
|
||||
# image, you'll need to: chmod -R a+rw .
|
||||
config.vm.provider "docker" do |docker, override|
|
||||
override.vm.box = nil
|
||||
docker.image = "jesselang/debian-vagrant:stretch"
|
||||
docker.build_dir = "util/vagrant"
|
||||
docker.has_ssh = true
|
||||
end
|
||||
|
||||
# This script ensures the required packages for AVR programming are installed
|
||||
# It also ensures the system always gets the latest updates when powered on
|
||||
# If this causes issues you can run a 'vagrant destroy' and then
|
||||
# add a # before ,run: (or change "always" to "once") and run 'vagrant up' to get a working
|
||||
# non-updated box and then attempt to troubleshoot or open a Github issue
|
||||
config.vm.provision "shell", inline: "/vagrant/util/qmk_install.sh", run: "always"
|
||||
# Unless we are running the docker container directly
|
||||
# 1. run container detached on vm
|
||||
# 2. attach on 'vagrant ssh'
|
||||
["virtualbox", "vmware_workstation", "vmware_fusion"].each do |type|
|
||||
config.vm.provider type do |virt, override|
|
||||
override.vm.provision "docker" do |d|
|
||||
d.run "qmkfm/base_container",
|
||||
cmd: "tail -f /dev/null",
|
||||
args: "--privileged -v /dev:/dev -v '/vagrant:/vagrant'"
|
||||
end
|
||||
|
||||
override.vm.provision "shell", inline: <<-SHELL
|
||||
echo 'docker restart qmkfm-base_container && exec docker exec -it qmkfm-base_container /bin/bash -l' >> ~vagrant/.bashrc
|
||||
SHELL
|
||||
end
|
||||
end
|
||||
|
||||
config.vm.post_up_message = <<-EOT
|
||||
|
||||
Log into the VM using 'vagrant ssh'. QMK directory synchronized with host is
|
||||
located at /vagrant
|
||||
Log into the environment using 'vagrant ssh'. QMK directory synchronized with
|
||||
host is located at /vagrant
|
||||
To compile the .hex files use make command inside this directory, e.g.
|
||||
cd /vagrant
|
||||
make <keyboard>:default
|
||||
|
97
bin/qmk
Executable file
97
bin/qmk
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""CLI wrapper for running QMK commands.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from glob import glob
|
||||
from time import strftime
|
||||
from importlib import import_module
|
||||
from importlib.util import find_spec
|
||||
|
||||
# Add the QMK python libs to our path
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
qmk_dir = os.path.abspath(os.path.join(script_dir, '..'))
|
||||
python_lib_dir = os.path.abspath(os.path.join(qmk_dir, 'lib', 'python'))
|
||||
sys.path.append(python_lib_dir)
|
||||
|
||||
# Change to the root of our checkout
|
||||
os.environ['ORIG_CWD'] = os.getcwd()
|
||||
os.chdir(qmk_dir)
|
||||
|
||||
# Make sure our modules have been setup
|
||||
with open('requirements.txt', 'r') as fd:
|
||||
for line in fd.readlines():
|
||||
line = line.strip().replace('<', '=').replace('>', '=')
|
||||
|
||||
if line[0] == '#':
|
||||
continue
|
||||
|
||||
if '#' in line:
|
||||
line = line.split('#')[0]
|
||||
|
||||
module = line.split('=')[0] if '=' in line else line
|
||||
if not find_spec(module):
|
||||
print('Your QMK build environment is not fully setup!\n')
|
||||
print('Please run `./util/qmk_install.sh` to setup QMK.')
|
||||
exit(255)
|
||||
|
||||
# Figure out our version
|
||||
command = ['git', 'describe', '--abbrev=6', '--dirty', '--always', '--tags']
|
||||
result = subprocess.run(command, universal_newlines=True, capture_output=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
os.environ['QMK_VERSION'] = 'QMK ' + result.stdout.strip()
|
||||
else:
|
||||
os.environ['QMK_VERSION'] = 'QMK ' + strftime('%Y-%m-%d-%H:%M:%S')
|
||||
|
||||
# Setup the CLI
|
||||
import milc
|
||||
milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}ψ{style_reset_all}'
|
||||
|
||||
# If we were invoked as `qmk <cmd>` massage sys.argv into `qmk-<cmd>`.
|
||||
# This means we can't accept arguments to the qmk script itself.
|
||||
script_name = os.path.basename(sys.argv[0])
|
||||
if script_name == 'qmk':
|
||||
if len(sys.argv) == 1:
|
||||
milc.cli.log.error('No subcommand specified!\n')
|
||||
|
||||
if len(sys.argv) == 1 or sys.argv[1] in ['-h', '--help']:
|
||||
milc.cli.echo('usage: qmk <subcommand> [...]')
|
||||
milc.cli.echo('\nsubcommands:')
|
||||
subcommands = glob(os.path.join(qmk_dir, 'bin', 'qmk-*'))
|
||||
for subcommand in sorted(subcommands):
|
||||
subcommand = os.path.basename(subcommand).split('-', 1)[1]
|
||||
milc.cli.echo('\t%s', subcommand)
|
||||
milc.cli.echo('\nqmk <subcommand> --help for more information')
|
||||
exit(1)
|
||||
|
||||
if sys.argv[1] in ['-V', '--version']:
|
||||
milc.cli.echo(os.environ['QMK_VERSION'])
|
||||
exit(0)
|
||||
|
||||
sys.argv[0] = script_name = '-'.join((script_name, sys.argv[1]))
|
||||
del sys.argv[1]
|
||||
|
||||
# Look for which module to import
|
||||
if script_name == 'qmk':
|
||||
milc.cli.print_help()
|
||||
exit(0)
|
||||
elif not script_name.startswith('qmk-'):
|
||||
milc.cli.log.error('Invalid symlink, must start with "qmk-": %s', script_name)
|
||||
else:
|
||||
subcommand = script_name.replace('-', '.').replace('_', '.').split('.')
|
||||
subcommand.insert(1, 'cli')
|
||||
subcommand = '.'.join(subcommand)
|
||||
|
||||
try:
|
||||
import_module(subcommand)
|
||||
except ModuleNotFoundError as e:
|
||||
if e.__class__.__name__ != subcommand:
|
||||
raise
|
||||
|
||||
milc.cli.log.error('Invalid subcommand! Could not import %s.', subcommand)
|
||||
exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
milc.cli()
|
1
bin/qmk-compile-json
Symbolic link
1
bin/qmk-compile-json
Symbolic link
@@ -0,0 +1 @@
|
||||
qmk
|
1
bin/qmk-doctor
Symbolic link
1
bin/qmk-doctor
Symbolic link
@@ -0,0 +1 @@
|
||||
qmk
|
1
bin/qmk-hello
Symbolic link
1
bin/qmk-hello
Symbolic link
@@ -0,0 +1 @@
|
||||
qmk
|
1
bin/qmk-json-keymap
Symbolic link
1
bin/qmk-json-keymap
Symbolic link
@@ -0,0 +1 @@
|
||||
qmk
|
@@ -76,6 +76,10 @@ ifeq ($(strip $(BOOTLOADER)), bootloadHID)
|
||||
OPT_DEFS += -DBOOTLOADER_BOOTLOADHID
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), USBasp)
|
||||
OPT_DEFS += -DBOOTLOADER_USBASP
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
|
||||
ifdef BOOTLOADER_SIZE
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=$(strip $(BOOTLOADER_SIZE))
|
||||
|
27
build_json.mk
Normal file
27
build_json.mk
Normal file
@@ -0,0 +1,27 @@
|
||||
# Look for a json keymap file
|
||||
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","")
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","")
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","")
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","")
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
endif
|
||||
|
||||
# Generate the keymap.c
|
||||
ifneq ("$(KEYMAP_JSON)","")
|
||||
_ = $(shell test -e $(KEYMAP_C) || bin/qmk-json-keymap $(KEYMAP_JSON) -o $(KEYMAP_C))
|
||||
endif
|
@@ -98,31 +98,38 @@ MAIN_KEYMAP_PATH_3 := $(KEYBOARD_PATH_3)/keymaps/$(KEYMAP)
|
||||
MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP)
|
||||
MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
|
||||
|
||||
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_5)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_4)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_3)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_2)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_1)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
else ifneq ($(LAYOUTS),)
|
||||
include build_layout.mk
|
||||
else
|
||||
$(error Could not find keymap)
|
||||
# this state should never be reached
|
||||
# Check for keymap.json first, so we can regenerate keymap.c
|
||||
include build_json.mk
|
||||
|
||||
ifeq ("$(wildcard $(KEYMAP_PATH))", "")
|
||||
# Look through the possible keymap folders until we find a matching keymap.c
|
||||
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_5)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_4)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_3)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_2)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_1)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
else ifneq ($(LAYOUTS),)
|
||||
# If we haven't found a keymap yet fall back to community layouts
|
||||
include build_layout.mk
|
||||
else
|
||||
$(error Could not find keymap)
|
||||
# this state should never be reached
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTPC)), yes)
|
||||
@@ -313,7 +320,6 @@ ifneq ("$(wildcard $(USER_PATH)/config.h)","")
|
||||
CONFIG_H += $(USER_PATH)/config.h
|
||||
endif
|
||||
|
||||
|
||||
# Object files directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
@@ -323,7 +329,7 @@ ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
|
||||
CONFIG_H += $(KEYMAP_PATH)/config.h
|
||||
endif
|
||||
|
||||
# # project specific files
|
||||
# project specific files
|
||||
SRC += $(KEYBOARD_SRC) \
|
||||
$(KEYMAP_C) \
|
||||
$(QUANTUM_SRC)
|
||||
@@ -392,6 +398,7 @@ $(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
|
||||
all: build check-size
|
||||
build: elf cpfirmware
|
||||
check-size: build
|
||||
objs-size: build
|
||||
|
||||
include show_options.mk
|
||||
include $(TMK_PATH)/rules.mk
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
* [QMK Basics](README.md)
|
||||
* [QMK Introduction](getting_started_introduction.md)
|
||||
* [QMK CLI](cli.md)
|
||||
* [Contributing to QMK](contributing.md)
|
||||
* [How to Use Github](getting_started_github.md)
|
||||
* [Getting Help](getting_started_getting_help.md)
|
||||
@@ -34,6 +35,8 @@
|
||||
* [Keyboard Guidelines](hardware_keyboard_guidelines.md)
|
||||
* [Config Options](config_options.md)
|
||||
* [Keycodes](keycodes.md)
|
||||
* [Coding Conventions - C](coding_conventions_c.md)
|
||||
* [Coding Conventions - Python](coding_conventions_python.md)
|
||||
* [Documentation Best Practices](documentation_best_practices.md)
|
||||
* [Documentation Templates](documentation_templates.md)
|
||||
* [Glossary](reference_glossary.md)
|
||||
@@ -41,6 +44,7 @@
|
||||
* [Useful Functions](ref_functions.md)
|
||||
* [Configurator Support](reference_configurator_support.md)
|
||||
* [info.json Format](reference_info_json.md)
|
||||
* [Python Development](python_development.md)
|
||||
|
||||
* [Features](features.md)
|
||||
* [Basic Keycodes](keycodes_basic.md)
|
||||
@@ -73,6 +77,7 @@
|
||||
* [RGB Lighting](feature_rgblight.md)
|
||||
* [RGB Matrix](feature_rgb_matrix.md)
|
||||
* [Space Cadet](feature_space_cadet.md)
|
||||
* [Split Keyboard](feature_split_keyboard.md)
|
||||
* [Stenography](feature_stenography.md)
|
||||
* [Swap Hands](feature_swap_hands.md)
|
||||
* [Tap Dance](feature_tap_dance.md)
|
||||
|
31
docs/cli.md
Normal file
31
docs/cli.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# QMK CLI
|
||||
|
||||
This page describes how to setup and use the QMK CLI.
|
||||
|
||||
# Overview
|
||||
|
||||
The QMK CLI makes building and working with QMK keyboards easier. We have provided a number of commands to help you work with QMK:
|
||||
|
||||
* `qmk compile-json`
|
||||
|
||||
# Setup
|
||||
|
||||
Simply add the `qmk_firmware/bin` directory to your `PATH`. You can run the `qmk` commands from any directory.
|
||||
|
||||
```
|
||||
export PATH=$PATH:$HOME/qmk_firmware/bin
|
||||
```
|
||||
|
||||
You may want to add this to your `.profile`, `.bash_profile`, `.zsh_profile`, or other shell startup scripts.
|
||||
|
||||
# Commands
|
||||
|
||||
## `qmk compile-json`
|
||||
|
||||
This command allows you to compile JSON files you have downloaded from <https://config.qmk.fm>.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk compile-json mine.json
|
||||
```
|
58
docs/coding_conventions_c.md
Normal file
58
docs/coding_conventions_c.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Coding Conventions (C)
|
||||
|
||||
Most of our style is pretty easy to pick up on, but right now it's not entirely consistent. You should match the style of the code surrounding your change, but if that code is inconsistent or unclear use the following guidelines:
|
||||
|
||||
* We indent using four (4) spaces (soft tabs)
|
||||
* We use a modified One True Brace Style
|
||||
* Opening Brace: At the end of the same line as the statement that opens the block
|
||||
* Closing Brace: Lined up with the first character of the statement that opens the block
|
||||
* Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
|
||||
* Optional Braces: Always include optional braces.
|
||||
* Good: if (condition) { return false; }
|
||||
* Bad: if (condition) return false;
|
||||
* We encourage use of C style comments: `/* */`
|
||||
* Think of them as a story describing the feature
|
||||
* Use them liberally to explain why particular decisions were made.
|
||||
* Do not write obvious comments
|
||||
* If you not sure if a comment is obvious, go ahead and include it.
|
||||
* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
|
||||
* We use `#pragma once` at the start of header files rather than old-style include guards (`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)
|
||||
* We accept both forms of preprocessor if's: `#ifdef DEFINED` and `#if defined(DEFINED)`
|
||||
* If you are not sure which to prefer use the `#if defined(DEFINED)` form.
|
||||
* Do not change existing code from one style to the other, except when moving to a multiple condition `#if`.
|
||||
* Do not put whitespace between `#` and `if`.
|
||||
* When deciding how (or if) to indent directives keep these points in mind:
|
||||
* Readability is more important than consistency.
|
||||
* Follow the file's existing style. If the file is mixed follow the style that makes sense for the section you are modifying.
|
||||
* When choosing to indent you can follow the indention level of the surrounding C code, or preprocessor directives can have their own indent level. Choose the style that best communicates the intent of your code.
|
||||
|
||||
Here is an example for easy reference:
|
||||
|
||||
```c
|
||||
/* Enums for foo */
|
||||
enum foo_state {
|
||||
FOO_BAR,
|
||||
FOO_BAZ,
|
||||
};
|
||||
|
||||
/* Returns a value */
|
||||
int foo(void) {
|
||||
if (some_condition) {
|
||||
return FOO_BAR;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Auto-formatting with clang-format
|
||||
|
||||
[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) is part of LLVM and can automatically format your code for you, because ain't nobody got time to do it manually. We supply a configuration file for it that applies most of the coding conventions listed above. It will only change whitespace and newlines, so you will still have to remember to include optional braces yourself.
|
||||
|
||||
Use the [full LLVM installer](http://llvm.org/builds/) to get clang-format on Windows, or use `sudo apt install clang-format` on Ubuntu.
|
||||
|
||||
If you run it from the command-line, pass `-style=file` as an option and it will automatically find the .clang-format configuration file in the QMK root directory.
|
||||
|
||||
If you use VSCode, the standard C/C++ plugin supports clang-format, alternatively there is a [separate extension](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) for it.
|
||||
|
||||
Some things (like LAYOUT macros) are destroyed by clang-format, so either don't run it on those files, or wrap the sensitive code in `// clang-format off` and `// clang-format on`.
|
314
docs/coding_conventions_python.md
Normal file
314
docs/coding_conventions_python.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# Coding Conventions (Python)
|
||||
|
||||
Most of our style follows PEP8 with some local modifications to make things less nit-picky.
|
||||
|
||||
* We target Python 3.5 for compatability with all supported platforms.
|
||||
* We indent using four (4) spaces (soft tabs)
|
||||
* We encourage liberal use of comments
|
||||
* Think of them as a story describing the feature
|
||||
* Use them liberally to explain why particular decisions were made.
|
||||
* Do not write obvious comments
|
||||
* If you not sure if a comment is obvious, go ahead and include it.
|
||||
* We require useful docstrings for all functions.
|
||||
* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
|
||||
* Some of our practices conflict with the wider python community to make our codebase more approachable to non-pythonistas.
|
||||
|
||||
# YAPF
|
||||
|
||||
You can use [yapf](https://github.com/google/yapf) to style your code. We provide a config in [setup.cfg](setup.cfg).
|
||||
|
||||
# Imports
|
||||
|
||||
We don't have a hard and fast rule for when to use `import ...` vs `from ... import ...`. Understandability and maintainability is our ultimate goal.
|
||||
|
||||
Generally we prefer to import specific function and class names from a module to keep code shorter and easier to understand. Sometimes this results in a name that is ambiguous, and in such cases we prefer to import the module instead. You should avoid using the "as" keyword when importing, unless you are importing a compatability module.
|
||||
|
||||
Imports should be one line per module. We group import statements together using the standard python rules- system, 3rd party, local.
|
||||
|
||||
Do not use `from foo import *`. Supply a list of objects you want to import instead, or import the whole module.
|
||||
|
||||
## Import Examples
|
||||
|
||||
Good:
|
||||
|
||||
```
|
||||
from qmk import effects
|
||||
|
||||
effects.echo()
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```
|
||||
from qmk.effects import echo
|
||||
|
||||
echo() # It's unclear where echo comes from
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```
|
||||
from qmk.keymap import compile_firmware
|
||||
|
||||
compile_firmware()
|
||||
```
|
||||
|
||||
OK, but the above is better:
|
||||
|
||||
```
|
||||
import qmk.keymap
|
||||
|
||||
qmk.keymap.compile_firmware()
|
||||
```
|
||||
|
||||
# Statements
|
||||
|
||||
One statement per line.
|
||||
|
||||
Even when allowed (EG `if foo: bar`) we do not combine 2 statements onto a single line.
|
||||
|
||||
# Naming
|
||||
|
||||
`module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, `function_parameter_name`, `local_var_name`.
|
||||
|
||||
Function names, variable names, and filenames should be descriptive; eschew abbreviation. In particular, do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word.
|
||||
|
||||
Always use a .py filename extension. Never use dashes.
|
||||
|
||||
## Names to Avoid
|
||||
|
||||
* single character names except for counters or iterators. You may use "e" as an exception identifier in try/except statements.
|
||||
* dashes (-) in any package/module name
|
||||
* __double_leading_and_trailing_underscore__ names (reserved by Python)
|
||||
|
||||
# Docstrings
|
||||
|
||||
To maintain consistency with our docstrings we've set out the following guidelines.
|
||||
|
||||
* Use markdown formatting
|
||||
* Always use triple-dquote docstrings with at least one linebreak: `"""\n"""`
|
||||
* First line is a short (< 70 char) description of what the function does
|
||||
* If you need more in your docstring leave a blank line between the description and the rest.
|
||||
* Start indented lines at the same indent level as the opening triple-dquote
|
||||
* Document all function arguments using the format described below
|
||||
* If present, Args:, Returns:, and Raises: should be the last three things in the docstring, separated by a blank line each.
|
||||
|
||||
## Simple docstring example
|
||||
|
||||
```
|
||||
def my_awesome_function():
|
||||
"""Return the number of seconds since 1970 Jan 1 00:00 UTC.
|
||||
"""
|
||||
return int(time.time())
|
||||
```
|
||||
|
||||
## Complex docstring example
|
||||
|
||||
```
|
||||
def my_awesome_function():
|
||||
"""Return the number of seconds since 1970 Jan 1 00:00 UTC.
|
||||
|
||||
This function always returns an integer number of seconds.
|
||||
"""
|
||||
return int(time.time())
|
||||
```
|
||||
|
||||
## Function arguments docstring example
|
||||
|
||||
```
|
||||
def my_awesome_function(start=None, offset=0):
|
||||
"""Return the number of seconds since 1970 Jan 1 00:00 UTC.
|
||||
|
||||
This function always returns an integer number of seconds.
|
||||
|
||||
|
||||
Args:
|
||||
start
|
||||
The time to start at instead of 1970 Jan 1 00:00 UTC
|
||||
|
||||
offset
|
||||
Return an answer that has this number of seconds subtracted first
|
||||
|
||||
Returns:
|
||||
An integer describing a number of seconds.
|
||||
|
||||
Raises:
|
||||
ValueError
|
||||
When `start` or `offset` are not positive numbers
|
||||
"""
|
||||
if start < 0 or offset < 0:
|
||||
raise ValueError('start and offset must be positive numbers.')
|
||||
|
||||
if not start:
|
||||
start = time.time()
|
||||
|
||||
return int(start - offset)
|
||||
```
|
||||
|
||||
# Exceptions
|
||||
|
||||
Exceptions are used to handle exceptional situations. They should not be used for flow control. This is a break from the python norm of "ask for forgiveness." If you are catching an exception it should be to handle a situation that is unusual.
|
||||
|
||||
If you use a catch-all exception for any reason you must log the exception and stacktrace using cli.log.
|
||||
|
||||
Make your try/except blocks as short as possible. If you need a lot of try statements you may need to restructure your code.
|
||||
|
||||
# Tuples
|
||||
|
||||
When defining one-item tuples always include a trailing comma so that it is obvious you are using a tuple. Do not rely on implicit one-item tuple unpacking. Better still use a list which is unambiguous.
|
||||
|
||||
This is particularly important when using the printf-style format strings that are commonly used.
|
||||
|
||||
# Lists and Dictionaries
|
||||
|
||||
We have configured YAPF to differentiate between sequence styles with a trailing comma. When a trailing comma is omitted YAPF will format the sequence as a single line. When a trailing comma is included YAPF will format the sequence with one item per line.
|
||||
|
||||
You should generally prefer to keep short definition on a single line. Break out to multiple lines sooner rather than later to aid readability and maintainability.
|
||||
|
||||
# Parentheses
|
||||
|
||||
Avoid excessive parentheses, but do use parentheses to make code easier to understand. Do not use them in return statements unless you are explicitly returning a tuple, or it is part of a math expression.
|
||||
|
||||
# Format Strings
|
||||
|
||||
We generally prefer printf-style format strings. Example:
|
||||
|
||||
```
|
||||
name = 'World'
|
||||
print('Hello, %s!' % (name,))
|
||||
```
|
||||
|
||||
This style is used by the logging module, which we make use of extensively, and we have adopted it in other places for consistency. It is also more familiar to C programmers, who are a big part of our casual audience.
|
||||
|
||||
Our included CLI module has support for using these without using the percent (%) operator. Look at `cli.echo()` and the various `cli.log` functions (EG, `cli.log.info()`) for more details.
|
||||
|
||||
# Comprehensions & Generator Expressions
|
||||
|
||||
We encourage the liberal use of comprehensions and generators, but do not let them get too complex. If you need complexity fall back to a for loop that is easier to understand.
|
||||
|
||||
# Lambdas
|
||||
|
||||
OK to use but probably should be avoided. With comprehensions and generators the need for lambdas is not as strong as it once was.
|
||||
|
||||
# Conditional Expressions
|
||||
|
||||
OK in variable assignment, but otherwise should be avoided.
|
||||
|
||||
Conditional expressions are if statements that are in line with code. For example:
|
||||
|
||||
```
|
||||
x = 1 if cond else 2
|
||||
```
|
||||
|
||||
It's generally not a good idea to use these as function arguments, sequence items, etc. It's too easy to overlook.
|
||||
|
||||
# Default Argument Values
|
||||
|
||||
Encouraged, but values must be immutable objects.
|
||||
|
||||
When specifying default values in argument lists always be careful to specify objects that can't be modified in place. If you use a mutable object the changes you make will persist between calls, which is usually not what you want. Even if that is what you intend to do it is confusing for others and will hinder understanding.
|
||||
|
||||
Bad:
|
||||
|
||||
```
|
||||
def my_func(foo={}):
|
||||
pass
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```
|
||||
def my_func(foo=None):
|
||||
if not foo:
|
||||
foo = {}
|
||||
```
|
||||
|
||||
# Properties
|
||||
|
||||
Always use properties instead of getter and setter functions.
|
||||
|
||||
```
|
||||
class Foo(object):
|
||||
def __init__(self):
|
||||
self._bar = None
|
||||
|
||||
@property
|
||||
def bar(self):
|
||||
return self._bar
|
||||
|
||||
@bar.setter
|
||||
def bar(self, bar):
|
||||
self._bar = bar
|
||||
```
|
||||
|
||||
# True/False Evaluations
|
||||
|
||||
You should generally prefer the implicit True/False evaluation in if statements, rather than checking equivalency.
|
||||
|
||||
Bad:
|
||||
|
||||
```
|
||||
if foo == True:
|
||||
pass
|
||||
|
||||
if bar == False:
|
||||
pass
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```
|
||||
if foo:
|
||||
pass
|
||||
|
||||
if not bar:
|
||||
pass
|
||||
```
|
||||
|
||||
# Decorators
|
||||
|
||||
Use when appropriate. Try to avoid too much magic unless it helps with understanding.
|
||||
|
||||
# Threading and Multiprocessing
|
||||
|
||||
Should be avoided. If you need this you will have to make a strong case before we merge your code.
|
||||
|
||||
# Power Features
|
||||
|
||||
Python is an extremely flexible language and gives you many fancy features such as custom metaclasses, access to bytecode, on-the-fly compilation, dynamic inheritance, object reparenting, import hacks, reflection, modification of system internals, etc.
|
||||
|
||||
Don't use these.
|
||||
|
||||
Performance is not a critical concern for us, and code understandability is. We want our codebase to be approachable by someone who only has a day or two to play with it. These features generally come with a cost to easy understanding, and we would prefer to have code that can be readily understood over faster or more compact code.
|
||||
|
||||
Note that some standard library modules use these techniques and it is ok to make use of those modules. But please keep readability and understandability in mind when using them.
|
||||
|
||||
# Type Annotated Code
|
||||
|
||||
For now we are not using any type annotation system, and would prefer that code remain unannotated. We may revisit this in the future.
|
||||
|
||||
# Function length
|
||||
|
||||
Prefer small and focused functions.
|
||||
|
||||
We recognize that long functions are sometimes appropriate, so no hard limit is placed on function length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program.
|
||||
|
||||
Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code.
|
||||
|
||||
You could find long and complicated functions when working with some code. Do not be intimidated by modifying existing code: if working with such a function proves to be difficult, you find that errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces.
|
||||
|
||||
# FIXMEs
|
||||
|
||||
It is OK to leave FIXMEs in code. Why? Encouraging people to at least document parts of code that need to be thought out more (or that are confusing) is better than leaving this code undocumented.
|
||||
|
||||
All FIXMEs should be formatted like:
|
||||
|
||||
```
|
||||
FIXME(username): Revisit this code when the frob feature is done.
|
||||
```
|
||||
|
||||
...where username is your GitHub username.
|
||||
|
||||
# Unit Tests
|
||||
|
||||
These are good. We should have some one day.
|
@@ -76,7 +76,7 @@ This is a C header file that is one of the first things included, and will persi
|
||||
* `#define B7_AUDIO`
|
||||
* enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
|
||||
* `#define BACKLIGHT_PIN B7`
|
||||
* pin of the backlight - `B5`, `B6`, `B7` and `C6` (and `D4` on ATmega32A) use hardware PWM, others use software implementation
|
||||
* pin of the backlight
|
||||
* `#define BACKLIGHT_LEVELS 3`
|
||||
* number of levels your backlight will have (maximum 15 excluding off)
|
||||
* `#define BACKLIGHT_BREATHING`
|
||||
@@ -89,7 +89,7 @@ This is a C header file that is one of the first things included, and will persi
|
||||
* mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap
|
||||
* `#define LOCKING_RESYNC_ENABLE`
|
||||
* tries to keep switch state consistent with keyboard LED state
|
||||
* `#define IS_COMMAND() (get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))`
|
||||
* `#define IS_COMMAND() (get_mods() == MOD_MASK_SHIFT)`
|
||||
* key combination that allows the use of magic commands (useful for debugging)
|
||||
* `#define USB_MAX_POWER_CONSUMPTION`
|
||||
* sets the maximum power (in mA) over USB for the device (default: 500)
|
||||
@@ -171,8 +171,8 @@ If you define these options you will enable the associated feature, which may in
|
||||
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
|
||||
* `#define TAP_CODE_DELAY 100`
|
||||
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds.
|
||||
* `#define TAP_HOLD_CAPS_DELAY 200`
|
||||
* Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 200ms if not defined.
|
||||
* `#define TAP_HOLD_CAPS_DELAY 80`
|
||||
* Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 80 ms if not defined. For macOS, you may want to set this to 200 or higher.
|
||||
|
||||
## RGB Light Configuration
|
||||
|
||||
@@ -248,6 +248,9 @@ There are a few different ways to set handedness for split keyboards (listed in
|
||||
* `#define MATRIX_COL_PINS_RIGHT { <col pins> }`
|
||||
* If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns.
|
||||
|
||||
* `#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }`
|
||||
* If you want to specify a different direct pinout for the right half than the left half, you can define `DIRECT_PINS_RIGHT`. Currently, the size of `DIRECT_PINS` must be the same as `DIRECT_PINS_RIGHT`.
|
||||
|
||||
* `#define RGBLED_SPLIT { 6, 6 }`
|
||||
* See [RGB Light Configuration](#rgb-light-configuration)
|
||||
|
||||
@@ -289,6 +292,7 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
|
||||
* `halfkay`
|
||||
* `caterina`
|
||||
* `bootloadHID`
|
||||
* `USBasp`
|
||||
|
||||
## Feature Options
|
||||
|
||||
|
@@ -54,62 +54,10 @@ Never made an open source contribution before? Wondering how contributions work
|
||||
|
||||
# Coding Conventions
|
||||
|
||||
Most of our style is pretty easy to pick up on, but right now it's not entirely consistent. You should match the style of the code surrounding your change, but if that code is inconsistent or unclear use the following guidelines:
|
||||
Most of our style is pretty easy to pick up on. If you are familiar with either C or Python you should not have too much trouble with our local styles.
|
||||
|
||||
* We indent using four (4) spaces (soft tabs)
|
||||
* We use a modified One True Brace Style
|
||||
* Opening Brace: At the end of the same line as the statement that opens the block
|
||||
* Closing Brace: Lined up with the first character of the statement that opens the block
|
||||
* Else If: Place the closing brace at the beginning of the line and the next opening brace at the end of the same line.
|
||||
* Optional Braces: Always include optional braces.
|
||||
* Good: if (condition) { return false; }
|
||||
* Bad: if (condition) return false;
|
||||
* We encourage use of C style comments: `/* */`
|
||||
* Think of them as a story describing the feature
|
||||
* Use them liberally to explain why particular decisions were made.
|
||||
* Do not write obvious comments
|
||||
* If you not sure if a comment is obvious, go ahead and include it.
|
||||
* In general we don't wrap lines, they can be as long as needed. If you do choose to wrap lines please do not wrap any wider than 76 columns.
|
||||
* We use `#pragma once` at the start of header files rather than old-style include guards (`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)
|
||||
* We accept both forms of preprocessor if's: `#ifdef DEFINED` and `#if defined(DEFINED)`
|
||||
* If you are not sure which to prefer use the `#if defined(DEFINED)` form.
|
||||
* Do not change existing code from one style to the other, except when moving to a multiple condition `#if`.
|
||||
* Do not put whitespace between `#` and `if`.
|
||||
* When deciding how (or if) to indent directives keep these points in mind:
|
||||
* Readability is more important than consistency.
|
||||
* Follow the file's existing style. If the file is mixed follow the style that makes sense for the section you are modifying.
|
||||
* When choosing to indent you can follow the indention level of the surrounding C code, or preprocessor directives can have their own indent level. Choose the style that best communicates the intent of your code.
|
||||
|
||||
Here is an example for easy reference:
|
||||
|
||||
```c
|
||||
/* Enums for foo */
|
||||
enum foo_state {
|
||||
FOO_BAR,
|
||||
FOO_BAZ,
|
||||
};
|
||||
|
||||
/* Returns a value */
|
||||
int foo(void) {
|
||||
if (some_condition) {
|
||||
return FOO_BAR;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Auto-formatting with clang-format
|
||||
|
||||
[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) is part of LLVM and can automatically format your code for you, because ain't nobody got time to do it manually. We supply a configuration file for it that applies most of the coding conventions listed above. It will only change whitespace and newlines, so you will still have to remember to include optional braces yourself.
|
||||
|
||||
Use the [full LLVM installer](http://llvm.org/builds/) to get clang-format on Windows, or use `sudo apt install clang-format` on Ubuntu.
|
||||
|
||||
If you run it from the command-line, pass `-style=file` as an option and it will automatically find the .clang-format configuration file in the QMK root directory.
|
||||
|
||||
If you use VSCode, the standard C/C++ plugin supports clang-format, alternatively there is a [separate extension](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) for it.
|
||||
|
||||
Some things (like LAYOUT macros) are destroyed by clang-format, so either don't run it on those files, or wrap the sensitive code in `// clang-format off` and `// clang-format on`.
|
||||
* [Coding Conventions - C](coding_conventions_c.md)
|
||||
* [Coding Conventions - Python](coding_conventions_python.md)
|
||||
|
||||
# General Guidelines
|
||||
|
||||
|
@@ -19,7 +19,11 @@ Note that running `make` with `sudo` is generally ***not*** a good idea, and you
|
||||
|
||||
### Linux `udev` Rules
|
||||
On Linux, you'll need proper privileges to access the MCU. You can either use
|
||||
`sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`.
|
||||
`sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`. Once added run the following:
|
||||
```console
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/50-atmel-dfu.rules:**
|
||||
```
|
||||
@@ -43,21 +47,41 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", MODE:="0666"
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/55-catalina.rules:**
|
||||
```
|
||||
# ModemManager should ignore the following devices
|
||||
ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
```
|
||||
|
||||
**Note:** ModemManager filtering only works when not in strict mode, the following commands can update that settings:
|
||||
```console
|
||||
sudo sed -i 's/--filter-policy=strict/--filter-policy=default/' /lib/systemd/system/ModemManager.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart ModemManager
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/56-dfu-util.rules:**
|
||||
```
|
||||
# stm32duino
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", MODE:="0666"
|
||||
# Generic stm32
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666"
|
||||
```
|
||||
|
||||
### Serial device is not detected in bootloader mode on Linux
|
||||
Make sure your kernel has appropriate support for your device. If your device uses USB ACM, such as
|
||||
Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices may require `USB_SERIAL` and any of its sub options.
|
||||
|
||||
## Unknown Device for DFU Bootloader
|
||||
|
||||
If you're using Windows to flash your keyboard, and you are running into issues, check the Device Manager. If you see an "Unknown Device" when the keyboard is in "bootloader mode", then you may have a driver issue.
|
||||
Issues encountered when flashing keyboards on Windows are most often due to having the wrong drivers installed for the bootloader.
|
||||
|
||||
Re-running the installation script for MSYS2 may help (eg run `./util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue.
|
||||
Re-running the installation script for MSYS2 may help (eg run `util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package.
|
||||
|
||||
If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, find the device in question, and select the `WinUSB` option, and hit "Reinstall driver". Once you've done that, try flashing your board, again. If that doesn't work, try all of the options, until one works.
|
||||
If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, and run it on the system. Then, you will need to reset your board into bootloader mode. After that, locate the device in question. If the device doesn't show up in the list (or nothing shows up in the list), you may need to enable the `List all devices` option in the `Options` menu.
|
||||
|
||||
?> There isn't a best option for which driver should be used here. Some options work better on some systems than others. libUSB and WinUSB seem to be the best options here.
|
||||
|
||||
If the bootloader doesn't show up in the list for devices, you may need to enable the "List all devices" option in the `Options` menu, and then find the bootloader in question.
|
||||
From here, you will need to know what type of controller the board is using. You may see it listed in the Device Manager as `ATmega32U4` device (which is an AVR board), or an `STM32` device (Which is an ARM board). For AVR boards, use `libusb-win32` for the driver. For ARM boards, use the `WinUSB` driver. Once the correct driver type has been selected, click on the `Replace Driver` button, unplug your board, plug it back in, and reset it again.
|
||||
|
||||
|
||||
## WINAVR is Obsolete
|
||||
|
@@ -87,6 +87,7 @@ Size after:
|
||||
- EEPROM has around a 100000 write cycle. You shouldn't rewrite the
|
||||
firmware repeatedly and continually; that'll burn the EEPROM
|
||||
eventually.
|
||||
|
||||
## NKRO Doesn't work
|
||||
First you have to compile firmware with this build option `NKRO_ENABLE` in **Makefile**.
|
||||
|
||||
|
@@ -30,32 +30,31 @@ You should then be able to use the keycodes below to change the backlight level.
|
||||
|
||||
This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously use multiple different coloured LEDs on a keyboard.
|
||||
|
||||
Hardware PWM is only supported on certain pins of the MCU, so if the backlighting is not connected to one of them, a software PWM implementation triggered by hardware timer interrupts will be used.
|
||||
|
||||
Hardware PWM is supported according to the following table:
|
||||
|
||||
| Backlight Pin | Hardware timer |
|
||||
|---------------|-------------------------|
|
||||
|`B5` | Timer 1 |
|
||||
|`B6` | Timer 1 |
|
||||
|`B7` | Timer 1 |
|
||||
|`C6` | Timer 3 |
|
||||
|`D4` | Timer 1 (ATmega32A only)|
|
||||
| other | Software PWM |
|
||||
|Backlight Pin|AT90USB64/128|ATmega16/32U4|ATmega16/32U2|ATmega32A|
|
||||
|-------------|-------------|-------------|-------------|---------|
|
||||
|`B5` |Timer 1 |Timer 1 | | |
|
||||
|`B6` |Timer 1 |Timer 1 | | |
|
||||
|`B7` |Timer 1 |Timer 1 |Timer 1 | |
|
||||
|`C4` |Timer 3 | | | |
|
||||
|`C5` |Timer 3 | |Timer 1 | |
|
||||
|`C6` |Timer 3 |Timer 3 |Timer 1 | |
|
||||
|`D4` | | | |Timer 1 |
|
||||
|`D5` | | | |Timer 1 |
|
||||
|
||||
The [audio feature](feature_audio.md) also uses hardware timers. Please refer to the following table to know what hardware timer the software PWM will use depending on the audio configuration:
|
||||
All other pins will use software PWM. If the [Audio](feature_audio.md) feature is disabled or only using one timer, the backlight PWM can be triggered by a hardware timer:
|
||||
|
||||
| Audio Pin(s) | Audio Timer | Software PWM Timer |
|
||||
|--------------|-------------|--------------------|
|
||||
| `C4` | Timer 3 | Timer 1 |
|
||||
| `C5` | Timer 3 | Timer 1 |
|
||||
| `C6` | Timer 3 | Timer 1 |
|
||||
| `B5` | Timer 1 | Timer 3 |
|
||||
| `B6` | Timer 1 | Timer 3 |
|
||||
| `B7` | Timer 1 | Timer 3 |
|
||||
| `Bx` & `Cx` | Timer 1 & 3 | None |
|
||||
|Audio Pin|Audio Timer|Software PWM Timer|
|
||||
|---------|-----------|------------------|
|
||||
|`C4` |Timer 3 |Timer 1 |
|
||||
|`C5` |Timer 3 |Timer 1 |
|
||||
|`C6` |Timer 3 |Timer 1 |
|
||||
|`B5` |Timer 1 |Timer 3 |
|
||||
|`B6` |Timer 1 |Timer 3 |
|
||||
|`B7` |Timer 1 |Timer 3 |
|
||||
|
||||
When all timers are in use for [audio](feature_audio.md), the backlight software PWM will not use a hardware timer, but instead will be triggered during the matrix scan. In this case the backlight doesn't support breathing and might show lighting artifacts (for instance flickering), because the PWM computation might not be called with enough timing precision.
|
||||
When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -65,7 +64,7 @@ To change the behaviour of the backlighting, `#define` these in your `config.h`:
|
||||
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PINS` |*Not defined*|experimental: see below for more information |
|
||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 15 excluding off) |
|
||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|
||||
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|
||||
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
||||
@@ -73,8 +72,10 @@ To change the behaviour of the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
## Backlight On State
|
||||
|
||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *low*.
|
||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case you must `#define BACKLIGHT_ON_STATE 1`, so that when the transistor is on, the pin is driven *high* instead.
|
||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
||||
|
||||
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
||||
|
||||
## Multiple backlight pins
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the tapping term would hit `ESC` instead, or have it perform even more complex tasks.
|
||||
|
||||
To enable this feature, yu need to add `COMBO_ENABLE = yes` to your `rules.mk`.
|
||||
To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`.
|
||||
|
||||
Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using).
|
||||
<!-- At this time, this is necessary -->
|
||||
@@ -59,19 +59,12 @@ void process_combo_event(uint8_t combo_index, bool pressed) {
|
||||
switch(combo_index) {
|
||||
case ZC_COPY:
|
||||
if (pressed) {
|
||||
register_code(KC_LCTL);
|
||||
register_code(KC_C);
|
||||
unregister_code(KC_C);
|
||||
unregister_code(KC_LCTL);
|
||||
tap_code16(LCTL(KC_C));
|
||||
}
|
||||
break;
|
||||
|
||||
case XV_PASTE:
|
||||
if (pressed) {
|
||||
register_code(KC_LCTL);
|
||||
register_code(KC_V);
|
||||
unregister_code(KC_V);
|
||||
unregister_code(KC_LCTL);
|
||||
tap_code16(LCTL(KC_V));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -87,3 +80,24 @@ If you're using long combos, or even longer combos, you may run into issues with
|
||||
In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file.
|
||||
|
||||
You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`.
|
||||
|
||||
## 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.
|
||||
|
||||
|Keycode |Description |
|
||||
|----------|---------------------------------|
|
||||
|`CMB_ON` |Turns on Combo feature |
|
||||
|`CMB_OFF` |Turns off Combo feature |
|
||||
|`CMB_TOG` |Toggles Combo feature on and off |
|
||||
|
||||
## User callbacks
|
||||
|
||||
In addition to the keycodes, there are a few functions that you can use to set the status, or check it:
|
||||
|
||||
|Function |Description |
|
||||
|-----------|--------------------------------------------------------------------|
|
||||
| `combo_enable()` | Enables the combo feature |
|
||||
| `combo_disable()` | Disables the combo feature, and clears the combo buffer |
|
||||
| `combo_toggle()` | Toggles the state of the combo feature |
|
||||
| `is_combo_enabled()` | Returns the status of the combo feature state (true or false) |
|
||||
|
@@ -16,36 +16,36 @@ To use Command, hold down the key combination defined by the `IS_COMMAND()` macr
|
||||
|
||||
If you would like to change the key assignments for Command, `#define` these in your `config.h` at either the keyboard or keymap level. All keycode assignments here must omit the `KC_` prefix.
|
||||
|
||||
|Define |Default |Description |
|
||||
|------------------------------------|---------------------------------------------------------------------------|------------------------------------------------|
|
||||
|`IS_COMMAND()` |<code>(get_mods() == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))</code>|The key combination to activate Command |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS` |`true` |Set default layer with the Function row |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS` |`true` |Set default layer with the number keys |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM`|`false` |Set default layer with `MAGIC_KEY_LAYER0..9` |
|
||||
|`MAGIC_KEY_DEBUG` |`D` |Toggle debugging over serial |
|
||||
|`MAGIC_KEY_DEBUG_MATRIX` |`X` |Toggle key matrix debugging |
|
||||
|`MAGIC_KEY_DEBUG_KBD` |`K` |Toggle keyboard debugging |
|
||||
|`MAGIC_KEY_DEBUG_MOUSE` |`M` |Toggle mouse debugging |
|
||||
|`MAGIC_KEY_CONSOLE` |`C` |Enable the Command console |
|
||||
|`MAGIC_KEY_VERSION` |`V` |Print the running QMK version to the console |
|
||||
|`MAGIC_KEY_STATUS` |`S` |Print the current keyboard status to the console|
|
||||
|`MAGIC_KEY_HELP` |`H` |Print Command help to the console |
|
||||
|`MAGIC_KEY_HELP_ALT` |`SLASH` |Print Command help to the console (alternate) |
|
||||
|`MAGIC_KEY_LAYER0` |`0` |Make layer 0 the default layer |
|
||||
|`MAGIC_KEY_LAYER0_ALT` |`GRAVE` |Make layer 0 the default layer (alternate) |
|
||||
|`MAGIC_KEY_LAYER1` |`1` |Make layer 1 the default layer |
|
||||
|`MAGIC_KEY_LAYER2` |`2` |Make layer 2 the default layer |
|
||||
|`MAGIC_KEY_LAYER3` |`3` |Make layer 3 the default layer |
|
||||
|`MAGIC_KEY_LAYER4` |`4` |Make layer 4 the default layer |
|
||||
|`MAGIC_KEY_LAYER5` |`5` |Make layer 5 the default layer |
|
||||
|`MAGIC_KEY_LAYER6` |`6` |Make layer 6 the default layer |
|
||||
|`MAGIC_KEY_LAYER7` |`7` |Make layer 7 the default layer |
|
||||
|`MAGIC_KEY_LAYER8` |`8` |Make layer 8 the default layer |
|
||||
|`MAGIC_KEY_LAYER9` |`9` |Make layer 9 the default layer |
|
||||
|`MAGIC_KEY_BOOTLOADER` |`B` |Jump to bootloader |
|
||||
|`MAGIC_KEY_BOOTLOADER_ALT` |`ESC` |Jump to bootloader (alternate) |
|
||||
|`MAGIC_KEY_LOCK` |`CAPS` |Lock the keyboard so nothing can be typed |
|
||||
|`MAGIC_KEY_EEPROM` |`E` |Print stored EEPROM config to the console |
|
||||
|`MAGIC_KEY_EEPROM_CLEAR` |`BSPACE` |Clear the EEPROM |
|
||||
|`MAGIC_KEY_NKRO` |`N` |Toggle N-Key Rollover (NKRO) |
|
||||
|`MAGIC_KEY_SLEEP_LED` |`Z` |Toggle LED when computer is sleeping |
|
||||
|Define |Default |Description |
|
||||
|------------------------------------|--------------------------------|------------------------------------------------|
|
||||
|`IS_COMMAND()` |`(get_mods() == MOD_MASK_SHIFT)`|The key combination to activate Command |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS` |`true` |Set default layer with the Function row |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS` |`true` |Set default layer with the number keys |
|
||||
|`MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM`|`false` |Set default layer with `MAGIC_KEY_LAYER0..9` |
|
||||
|`MAGIC_KEY_DEBUG` |`D` |Toggle debugging over serial |
|
||||
|`MAGIC_KEY_DEBUG_MATRIX` |`X` |Toggle key matrix debugging |
|
||||
|`MAGIC_KEY_DEBUG_KBD` |`K` |Toggle keyboard debugging |
|
||||
|`MAGIC_KEY_DEBUG_MOUSE` |`M` |Toggle mouse debugging |
|
||||
|`MAGIC_KEY_CONSOLE` |`C` |Enable the Command console |
|
||||
|`MAGIC_KEY_VERSION` |`V` |Print the running QMK version to the console |
|
||||
|`MAGIC_KEY_STATUS` |`S` |Print the current keyboard status to the console|
|
||||
|`MAGIC_KEY_HELP` |`H` |Print Command help to the console |
|
||||
|`MAGIC_KEY_HELP_ALT` |`SLASH` |Print Command help to the console (alternate) |
|
||||
|`MAGIC_KEY_LAYER0` |`0` |Make layer 0 the default layer |
|
||||
|`MAGIC_KEY_LAYER0_ALT` |`GRAVE` |Make layer 0 the default layer (alternate) |
|
||||
|`MAGIC_KEY_LAYER1` |`1` |Make layer 1 the default layer |
|
||||
|`MAGIC_KEY_LAYER2` |`2` |Make layer 2 the default layer |
|
||||
|`MAGIC_KEY_LAYER3` |`3` |Make layer 3 the default layer |
|
||||
|`MAGIC_KEY_LAYER4` |`4` |Make layer 4 the default layer |
|
||||
|`MAGIC_KEY_LAYER5` |`5` |Make layer 5 the default layer |
|
||||
|`MAGIC_KEY_LAYER6` |`6` |Make layer 6 the default layer |
|
||||
|`MAGIC_KEY_LAYER7` |`7` |Make layer 7 the default layer |
|
||||
|`MAGIC_KEY_LAYER8` |`8` |Make layer 8 the default layer |
|
||||
|`MAGIC_KEY_LAYER9` |`9` |Make layer 9 the default layer |
|
||||
|`MAGIC_KEY_BOOTLOADER` |`B` |Jump to bootloader |
|
||||
|`MAGIC_KEY_BOOTLOADER_ALT` |`ESC` |Jump to bootloader (alternate) |
|
||||
|`MAGIC_KEY_LOCK` |`CAPS` |Lock the keyboard so nothing can be typed |
|
||||
|`MAGIC_KEY_EEPROM` |`E` |Print stored EEPROM config to the console |
|
||||
|`MAGIC_KEY_EEPROM_CLEAR` |`BSPACE` |Clear the EEPROM |
|
||||
|`MAGIC_KEY_NKRO` |`N` |Toggle N-Key Rollover (NKRO) |
|
||||
|`MAGIC_KEY_SLEEP_LED` |`Z` |Toggle LED when computer is sleeping |
|
||||
|
@@ -6,7 +6,6 @@ Basic encoders are supported by adding this to your `rules.mk`:
|
||||
|
||||
and this to your `config.h`:
|
||||
|
||||
#define NUMBER_OF_ENCODERS 1
|
||||
#define ENCODERS_PAD_A { B12 }
|
||||
#define ENCODERS_PAD_B { B13 }
|
||||
|
||||
|
190
docs/feature_split_keyboard.md
Normal file
190
docs/feature_split_keyboard.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Split Keyboard
|
||||
|
||||
Many keyboards in the QMK Firmware repo are "split" keyboards. They use two controllers—one plugging into USB, and the second connected by a serial or an I<sup>2</sup>C connection over a TRRS or similar cable.
|
||||
|
||||
Split keyboards can have a lot of benefits, but there is some additional work needed to get them enabled.
|
||||
|
||||
QMK Firmware has a generic implementation that is usable by any board, as well as numerous board specific implementations.
|
||||
|
||||
For this, we will mostly be talking about the generic implementation used by the Let's Split and other keyboards.
|
||||
|
||||
!> ARM is not yet supported for Split Keyboards. Progress is being made, but we are not quite there, yet.
|
||||
|
||||
|
||||
## Hardware Configuration
|
||||
|
||||
This assumes that you're using two Pro Micro-compatible controllers, and are using TRRS jacks to connect to two halves.
|
||||
|
||||
### Required Hardware
|
||||
|
||||
Apart from diodes and key switches for the keyboard matrix in each half, you will need 2x TRRS sockets and 1x TRRS cable.
|
||||
|
||||
Alternatively, you can use any sort of cable and socket that has at least 3 wires.
|
||||
|
||||
If you want to use I<sup>2</sup>C to communicate between halves, you will need a cable with at least 4 wires and 2x 4.7kΩ pull-up resistors.
|
||||
|
||||
#### Considerations
|
||||
|
||||
The most commonly used connection is a TRRS cable and jacks. These provide 4 wires, making them very useful for split keyboards, and are easy to find.
|
||||
|
||||
However, since one of the wires carries VCC, this means that the boards are not hot pluggable. You should always disconnect the board from USB before unplugging and plugging in TRRS cables, or you can short the controller, or worse.
|
||||
|
||||
Another option is to use phone cables (as in, old school RJ-11/RJ-14 cables). Make sure that you use one that actually supports 4 wires/lanes.
|
||||
|
||||
However, USB cables, SATA cables, and even just 4 wires have been known to be used for communication between the controllers.
|
||||
|
||||
!> Using USB cables for communication between the controllers works just fine, but the connector could be mistaken for a normal USB connection and potentially short out the keyboard, depending on how it's wired. For this reason, they are not recommended for connecting split keyboards.
|
||||
|
||||
### Serial Wiring
|
||||
|
||||
The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and D0 (aka PDO or pin 3) between the two Pro Micros.
|
||||
|
||||
?> Note that the pin used here is actually set by `SOFT_SERIAL_PIN` below.
|
||||
|
||||

|
||||
|
||||
### I<sup>2</sup>C Wiring
|
||||
|
||||
The 4 wires of the TRRS cable need to connect GND, VCC, and SCL and SDA (aka PD0/pin 3 and PD1/pin 2, respectively) between the two Pro Micros.
|
||||
|
||||
The pull-up resistors may be placed on either half. It is also possible to use 4 resistors and have the pull-ups in both halves, but this is unnecessary in simple use cases.
|
||||
|
||||

|
||||
|
||||
## Firmware Configuration
|
||||
|
||||
To enable the split keyboard feature, add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
SPLIT_KEYBOARD = yes
|
||||
```
|
||||
|
||||
If you're using a custom transport (communication method), then you will also need to add:
|
||||
|
||||
```make
|
||||
SPLIT_TRANSPORT = custom
|
||||
```
|
||||
|
||||
### Setting Handedness
|
||||
|
||||
By default, the firmware does not know which side is which; it needs some help to determine that. There are several ways to do this, listed in order of precedence.
|
||||
|
||||
#### Handedness by Pin
|
||||
|
||||
You can configure the firmware to read a pin on the controller to determine handedness. To do this, add the following to your `config.h` file:
|
||||
|
||||
```c
|
||||
#define SPLIT_HAND_PIN B7
|
||||
```
|
||||
|
||||
This will read the specified pin. If it's high, then the controller assumes it is the left hand, and if it's low, it's assumed to be the right side.
|
||||
|
||||
#### Handedness by EEPROM
|
||||
|
||||
This method sets the keyboard's handedness by setting a flag in the persistent storage (`EEPROM`). This is checked when the controller first starts up, and determines what half the keyboard is, and how to orient the keyboard layout.
|
||||
|
||||
|
||||
To enable this method, add the following to your `config.h` file:
|
||||
|
||||
```c
|
||||
#define EE_HANDS
|
||||
```
|
||||
|
||||
However, you'll have to flash the EEPROM files for the correct hand to each controller. You can do this manually, or there are targets for avrdude and dfu to do this, while flashing the firmware:
|
||||
|
||||
* `:avrdude-split-left`
|
||||
* `:avrdude-split-right`
|
||||
* `:dfu-split-left`
|
||||
* `:dfu-split-right`
|
||||
|
||||
This setting is not changed when re-initializing the EEPROM using the `EEP_RST` key, or using the `eeconfig_init()` function. However, if you reset the EEPROM outside of the firmware's built in options (such as flashing a file that overwrites the `EEPROM`, like how the [QMK Toolbox]()'s "Reset EEPROM" button works), you'll need to re-flash the controller with the `EEPROM` files.
|
||||
|
||||
You can find the `EEPROM` files in the QMK firmware repo, [here](https://github.com/qmk/qmk_firmware/tree/master/quantum/split_common).
|
||||
|
||||
#### Handedness by `#define`
|
||||
|
||||
You can set the handedness at compile time. This is done by adding the following to your `config.h` file:
|
||||
|
||||
```c
|
||||
#define MASTER_RIGHT
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```c
|
||||
#define MASTER_LEFT
|
||||
```
|
||||
|
||||
If neither are defined, the handedness defaults to `MASTER_LEFT`.
|
||||
|
||||
|
||||
### Communication Options
|
||||
|
||||
Because not every split keyboard is identical, there are a number of additional options that can be configured in your `config.h` file.
|
||||
|
||||
```c
|
||||
#define USE_I2C
|
||||
```
|
||||
|
||||
This enables I<sup>2</sup>C support for split keyboards. This isn't strictly for communication, but can be used for OLED or other I<sup>2</sup>C-based devices.
|
||||
|
||||
```c
|
||||
#define SOFT_SERIAL_PIN D0
|
||||
```
|
||||
|
||||
This sets the pin to be used for serial communication. If you're not using serial, you shouldn't need to define this.
|
||||
|
||||
However, if you are using serial and I<sup>2</sup>C on the board, you will need to set this, and to something other than D0 and D1 (as these are used for I<sup>2</sup>C communication).
|
||||
|
||||
```c
|
||||
#define SELECT_SOFT_SERIAL_SPEED {#}`
|
||||
```
|
||||
|
||||
If you're having issues with serial communication, you can change this value, as it controls the communication speed for serial. The default is 1, and the possible values are:
|
||||
|
||||
* **`0`**: about 189kbps (Experimental only)
|
||||
* **`1`**: about 137kbps (default)
|
||||
* **`2`**: about 75kbps
|
||||
* **`3`**: about 39kbps
|
||||
* **`4`**: about 26kbps
|
||||
* **`5`**: about 20kbps
|
||||
|
||||
### Hardware Configuration Options
|
||||
|
||||
There are some settings that you may need to configure, based on how the hardware is set up.
|
||||
|
||||
```c
|
||||
#define MATRIX_ROW_PINS_RIGHT { <row pins> }
|
||||
#define MATRIX_COL_PINS_RIGHT { <col pins> }
|
||||
```
|
||||
|
||||
This allows you to specify a different set of pins for the matrix on the right side. This is useful if you have a board with differently-shaped halves that requires a different configuration (such as Keebio's Quefrency).
|
||||
|
||||
```c
|
||||
#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }
|
||||
```
|
||||
|
||||
This allows you to specify a different set of direct pins for the right side.
|
||||
|
||||
```c
|
||||
#define RGBLIGHT_SPLIT
|
||||
```
|
||||
|
||||
This option enables synchronization of the RGB Light modes between the controllers of the split keyboard. This is for keyboards that have RGB LEDs that are directly wired to the controller (that is, they are not using the "extra data" option on the TRRS cable).
|
||||
|
||||
```c
|
||||
#define RGBLED_SPLIT { 6, 6 }
|
||||
```
|
||||
|
||||
This sets how many LEDs are directly connected to each controller. The first number is the left side, and the second number is the right side.
|
||||
|
||||
?> This setting implies that `RGBLIGHT_SPLIT` is enabled, and will forcibly enable it, if it's not.
|
||||
|
||||
|
||||
## Additional Resources
|
||||
|
||||
Nicinabox has a [very nice and detailed guide](https://github.com/nicinabox/lets-split-guide) for the Let's Split keyboard, that covers most everything you need to know, including troubleshooting information.
|
||||
|
||||
However, the RGB Light section is out of date, as it was written long before the RGB Split code was added to QMK Firmware. Instead, wire each strip up directly to the controller.
|
||||
|
||||
<!-- I may port this information later, but for now ... it's very nice, and covers everything -->
|
@@ -1,22 +1,33 @@
|
||||
# Tap Dance: A Single Key Can Do 3, 5, or 100 Different Things
|
||||
|
||||
<!-- FIXME: Break this up into multiple sections -->
|
||||
|
||||
## Introduction
|
||||
Hit the semicolon key once, send a semicolon. Hit it twice, rapidly -- send a colon. Hit it three times, and your keyboard's LEDs do a wild dance. That's just one example of what Tap Dance can do. It's one of the nicest community-contributed features in the firmware, conceived and created by [algernon](https://github.com/algernon) in [#451](https://github.com/qmk/qmk_firmware/pull/451). Here's how algernon describes the feature:
|
||||
|
||||
With this feature one can specify keys that behave differently, based on the amount of times they have been tapped, and when interrupted, they get handled before the interrupter.
|
||||
|
||||
To make it clear how this is different from `ACTION_FUNCTION_TAP`, let's explore a certain setup! We want one key to send `Space` on single tap, but `Enter` on double-tap.
|
||||
## Explanatory Comparison with `ACTION_FUNCTION_TAP`
|
||||
`ACTION_FUNCTION_TAP` can offer similar functionality to Tap Dance, but it's worth noting some important differences. To do this, let's explore a certain setup! We want one key to send `Space` on single-tap, but `Enter` on double-tap.
|
||||
|
||||
With `ACTION_FUNCTION_TAP`, it is quite a rain-dance to set this up, and has the problem that when the sequence is interrupted, the interrupting key will be sent first. Thus, `SPC a` will result in `a SPC` being sent, if they are typed within `TAPPING_TERM`. With the tap dance feature, that'll come out as `SPC a`, correctly.
|
||||
With `ACTION_FUNCTION_TAP`, it is quite a rain-dance to set this up, and has the problem that when the sequence is interrupted, the interrupting key will be sent first. Thus, `SPC a` will result in `a SPC` being sent, if `SPC` and `a` are both typed within `TAPPING_TERM`. With the Tap Dance feature, that'll come out correctly as `SPC a` (even if both `SPC` and `a` are typed within the `TAPPING_TERM`.
|
||||
|
||||
The implementation hooks into two parts of the system, to achieve this: into `process_record_quantum()`, and the matrix scan. We need the latter to be able to time out a tap sequence even when a key is not being pressed, so `SPC` alone will time out and register after `TAPPING_TERM` time.
|
||||
To achieve this correct handling of interrupts, the implementation of Tap Dance hooks into two parts of the system: `process_record_quantum()`, and the matrix scan. These two parts are explained below, but for now the point to note is that we need the latter to be able to time out a tap sequence even when a key is not being pressed. That way, `SPC` alone will time out and register after `TAPPING_TERM` time.
|
||||
|
||||
But lets start with how to use it, first!
|
||||
## How to Use Tap Dance
|
||||
But enough of the generalities; lets look at how to actually use Tap Dance!
|
||||
|
||||
First, you will need `TAP_DANCE_ENABLE=yes` in your `rules.mk`, because the feature is disabled by default. This adds a little less than 1k to the firmware size. Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that - similar to `F()`, takes a number, which will later be used as an index into the `tap_dance_actions` array.
|
||||
First, you will need `TAP_DANCE_ENABLE=yes` in your `rules.mk`, because the feature is disabled by default. This adds a little less than 1k to the firmware size.
|
||||
|
||||
This array specifies what actions shall be taken when a tap-dance key is in action. Currently, there are five possible options:
|
||||
Optionally, you might want to set a custom `TAPPING_TERM` time by adding something like this in you `config.h`:
|
||||
|
||||
```
|
||||
#define TAPPING_TERM 175
|
||||
```
|
||||
|
||||
The `TAPPING_TERM` time is the maximum time allowed between taps of your Tap Dance key, and is measured in milliseconds. For example, if you used the above `#define` statement and set up a Tap Dance key that sends `Space` on single-tap and `Enter` on double-tap, then this key will send `ENT` only if you tap this key twice in less than 175ms. If you tap the key, wait more than 175ms, and tap the key again you'll end up sending `SPC SPC` instead.
|
||||
|
||||
Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that - similar to `F()` - takes a number, which will later be used as an index into the `tap_dance_actions` array.
|
||||
|
||||
After this, you'll want to use the `tap_dance_actions` array to specify what actions shall be taken when a tap-dance key is in action. Currently, there are five possible options:
|
||||
|
||||
* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: Sends the `kc1` keycode when tapped once, `kc2` otherwise. When the key is held, the appropriate keycode is registered: `kc1` when pressed and held, `kc2` when tapped once, then pressed and held.
|
||||
* `ACTION_TAP_DANCE_DUAL_ROLE(kc, layer)`: Sends the `kc` keycode when tapped once, or moves to `layer`. (this functions like the `TO` layer keycode).
|
||||
@@ -24,17 +35,22 @@ This array specifies what actions shall be taken when a tap-dance key is in acti
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED_TIME(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn, tap_specific_tapping_term)`: This functions identically to the `ACTION_TAP_DANCE_FN_ADVANCED` function, but uses a custom tapping term for it, instead of the predefined `TAPPING_TERM`.
|
||||
|
||||
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
|
||||
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
|
||||
|
||||
!> Keep in mind that only [basic keycodes](keycodes_basic.md) are supported here. Custom keycodes are not supported.
|
||||
|
||||
And that's the bulk of it!
|
||||
Similar to the first option, the second option is good for simple layer-switching cases.
|
||||
|
||||
And now, on to the explanation of how it works!
|
||||
For more complicated cases, use the third or fourth options (examples of each are listed below).
|
||||
|
||||
The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and the timer.
|
||||
Finally, the fifth option is particularly useful if your non-Tap-Dance keys start behaving weirdly after adding the code for your Tap Dance keys. The likely problem is that you changed the `TAPPING_TERM` time to make your Tap Dance keys easier for you to use, and that this has changed the way your other keys handle interrupts.
|
||||
|
||||
This means that you have `TAPPING_TERM` time to tap the key again, you do not have to input all the taps within that timeframe. This allows for longer tap counts, with minimal impact on responsiveness.
|
||||
## Implementation Details
|
||||
Well, that's the bulk of it! You should now be able to work through the examples below, and to develop your own Tap Dance functionality. But if you want a deeper understanding of what's going on behind the scenes, then read on for the explanation of how it all works!
|
||||
|
||||
The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and reset the timer.
|
||||
|
||||
This means that you have `TAPPING_TERM` time to tap the key again; you do not have to input all the taps within a single `TAPPING_TERM` timeframe. This allows for longer tap counts, with minimal impact on responsiveness.
|
||||
|
||||
Our next stop is `matrix_scan_tap_dance()`. This handles the timeout of tap-dance keys.
|
||||
|
||||
@@ -397,3 +413,111 @@ qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
```
|
||||
|
||||
Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.
|
||||
|
||||
### Example 6: Using tap dance for momentary-layer-switch and layer-toggle keys
|
||||
|
||||
Tap Dance can be used to mimic MO(layer) and TG(layer) functionality. For this example, we will set up a key to function as `KC_QUOT` on single-tap, as `MO(_MY_LAYER)` on single-hold, and `TG(_MY_LAYER)` on double-tap.
|
||||
|
||||
The first step is to include the following code towards the beginning of your `keymap.c`:
|
||||
|
||||
```
|
||||
typedef struct {
|
||||
bool is_press_action;
|
||||
int state;
|
||||
} tap;
|
||||
|
||||
//Define a type for as many tap dance states as you need
|
||||
enum {
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD = 2,
|
||||
DOUBLE_TAP = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
QUOT_LAYR = 0 //Our custom tap dance key; add any other tap dance keys to this enum
|
||||
};
|
||||
|
||||
//Declare the functions to be used with your tap dance key(s)
|
||||
|
||||
//Function associated with all tap dances
|
||||
int cur_dance (qk_tap_dance_state_t *state);
|
||||
|
||||
//Functions associated with individual tap dances
|
||||
void ql_finished (qk_tap_dance_state_t *state, void *user_data);
|
||||
void ql_reset (qk_tap_dance_state_t *state, void *user_data);
|
||||
|
||||
//Declare variable to track which layer is active
|
||||
int active_layer;
|
||||
```
|
||||
|
||||
The above code is similar to that used in previous examples. The one point to note is that you need to declare a variable to keep track of what layer is currently the active layer. We'll see why shortly.
|
||||
|
||||
Towards the bottom of your `keymap.c`, include the following code:
|
||||
|
||||
```
|
||||
//Update active_layer
|
||||
uint32_t layer_state_set_user(uint32_t state) {
|
||||
switch (biton32(state)) {
|
||||
case 1:
|
||||
active_layer = 1;
|
||||
break;
|
||||
case 2:
|
||||
active_layer = 2;
|
||||
break;
|
||||
case 3:
|
||||
active_layer = 3;
|
||||
break;
|
||||
default:
|
||||
active_layer = 0;
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
//Determine the current tap dance state
|
||||
int cur_dance (qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (!state->pressed) {return SINGLE_TAP;}
|
||||
else return SINGLE_HOLD;
|
||||
} else if (state->count == 2) {return DOUBLE_TAP;}
|
||||
else return 8;
|
||||
}
|
||||
|
||||
//Initialize tap structure associated with example tap dance key
|
||||
static tap ql_tap_state = {
|
||||
.is_press_action = true,
|
||||
.state = 0
|
||||
};
|
||||
|
||||
//Functions that control what our tap dance key does
|
||||
void ql_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||
ql_tap_state.state = cur_dance(state);
|
||||
switch (ql_tap_state.state) {
|
||||
case SINGLE_TAP: tap_code(KC_QUOT); break;
|
||||
case SINGLE_HOLD: layer_on(_MY_LAYER); break;
|
||||
case DOUBLE_TAP:
|
||||
if (active_layer==_MY_LAYER) {layer_off(_MY_LAYER);}
|
||||
else layer_on(_MY_LAYER);
|
||||
}
|
||||
}
|
||||
|
||||
void ql_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (ql_tap_state.state==SINGLE_HOLD) {layer_off(_MY_LAYER);}
|
||||
ql_tap_state.state = 0;
|
||||
}
|
||||
|
||||
//Associate our tap dance key with its functionality
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275)
|
||||
};
|
||||
```
|
||||
|
||||
The is where the real logic of our tap dance key gets worked out. Since `layer_state_set_user()` is called on any layer switch, we use it to update `active_layer`. Our example is assuming that your `keymap.c` includes 4 layers, so adjust the switch statement here to fit your actual number of layers.
|
||||
|
||||
The use of `cur_dance()` and `ql_tap_state` mirrors the above examples.
|
||||
|
||||
The `case:SINGLE_TAP` in `ql_finished` is similar to the above examples. The `case:SINGLE_HOLD` works in conjunction with `ql_reset()` to switch to `_MY_LAYER` while the tap dance key is held, and to switch away from `_MY_LAYER` when the key is released. This mirrors the use of `MO(_MY_LAYER)`. The `case:DOUBLE_TAP` works by checking whether `_MY_LAYER` is the active layer, and toggling it on or off accordingly. This mirrors the use of `TG(_MY_LAYER)`.
|
||||
|
||||
`tap_dance_actions[]` works similar to the above examples. Note that I used `ACTION_TAP_DANCE_FN_ADVANCED_TIME()` instead of `ACTION_TAP_DANCE_FN_ADVANCED()`. This is because I like my `TAPPING_TERM` to be short (~175ms) for my non-tap-dance keys but find that this is too quick for me to reliably complete tap dance actions - thus the increased time of 275ms here.
|
||||
|
||||
Finally, to get this tap dance key working, be sure to include `TD(QUOT_LAYR)` in your `keymaps[]`.
|
||||
|
@@ -1,28 +1,44 @@
|
||||
# Unicode Support
|
||||
|
||||
There are three Unicode keymap definition methods available in QMK:
|
||||
Unicode characters can be input straight from your keyboard! There are some limitations, however.
|
||||
|
||||
## `UNICODE_ENABLE`
|
||||
QMK has three different methods for enabling Unicode input and defining keycodes:
|
||||
|
||||
Supports Unicode up to `0x7FFF`. This covers characters for most modern languages, as well as symbols, but it doesn't cover emoji. The keycode function is `UC(c)` in the keymap, where _c_ is the code point's number (preferably hexadecimal, up to 4 digits long). For example: `UC(0x45B)`, `UC(0x30C4)`.
|
||||
## Basic Unicode
|
||||
|
||||
## `UNICODEMAP_ENABLE`
|
||||
This method supports Unicode code points up to `0x7FFF`. This covers characters for most modern languages, as well as symbols, but it doesn't cover emoji.
|
||||
|
||||
Supports Unicode up to `0x10FFFF` (all possible code points). You need to maintain a separate mapping table `const uint32_t PROGMEM unicode_map[] = {...}` in your keymap file. The keycode function is `X(i)`, where _i_ is an array index into the mapping table. The table may contain at most 16384 entries.
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
You may want to have an enum to make referencing easier. So, you could add something like this to your keymap file:
|
||||
```make
|
||||
UNICODE_ENABLE = yes
|
||||
```
|
||||
|
||||
Then add `UC(c)` keycodes to your keymap, where _c_ is the code point (preferably in hexadecimal, up to 4 digits long). For example: `UC(0x45B)`, `UC(0x30C4)`.
|
||||
|
||||
## Unicode Map
|
||||
|
||||
This method supports all possible code points (up to `0x10FFFF`); however, you need to maintain a separate mapping table in your keymap file, which may contain at most 16384 entries.
|
||||
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
UNICODEMAP_ENABLE = yes
|
||||
```
|
||||
|
||||
Then add `X(i)` keycodes to your keymap, where _i_ is an array index into the mapping table:
|
||||
|
||||
```c
|
||||
enum unicode_names {
|
||||
BANG,
|
||||
IRONY,
|
||||
SNEK,
|
||||
BANG,
|
||||
IRONY,
|
||||
SNEK
|
||||
};
|
||||
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
[BANG] = 0x203D, // ‽
|
||||
[IRONY] = 0x2E2E, // ⸮
|
||||
[SNEK] = 0x1F40D, // 🐍
|
||||
[BANG] = 0x203D, // ‽
|
||||
[IRONY] = 0x2E2E, // ⸮
|
||||
[SNEK] = 0x1F40D, // 🐍
|
||||
};
|
||||
```
|
||||
|
||||
@@ -30,27 +46,33 @@ Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
|
||||
|
||||
### Lower and Upper Case
|
||||
|
||||
Characters often come in lower and upper case pairs, for example: å, Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
|
||||
Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
|
||||
|
||||
This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP`. This blends Unicode keys in with regular alphas.
|
||||
This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP()`. This helps blend Unicode keys in with regular alphas.
|
||||
|
||||
Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L40) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
|
||||
|
||||
## `UCIS_ENABLE`
|
||||
## UCIS
|
||||
|
||||
Supports Unicode up to `0x10FFFF` (all possible code points). As with `UNICODEMAP`, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature — you have to add a keycode or function that calls `qk_ucis_start()`. Once this function has been called, you can type the corresponding mnemonic for your character, then hit Space or Enter to complete it, or Esc to cancel. If the mnemonic matches an entry in your table, the typed text will automatically be erased and the corresponding Unicode character inserted.
|
||||
This method also supports all possible code points. As with the Unicode Map method, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature — you have to create a custom keycode or function that invokes this functionality.
|
||||
|
||||
For instance, you could define a table like this in your keymap file:
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
UCIS_ENABLE = yes
|
||||
```
|
||||
|
||||
Then define a table like this in your keymap file:
|
||||
|
||||
```c
|
||||
const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
|
||||
UCIS_SYM("poop", 0x1F4A9), // 💩
|
||||
UCIS_SYM("rofl", 0x1F923), // 🤣
|
||||
UCIS_SYM("kiss", 0x1F619) // 😙
|
||||
UCIS_SYM("poop", 0x1F4A9), // 💩
|
||||
UCIS_SYM("rofl", 0x1F923), // 🤣
|
||||
UCIS_SYM("kiss", 0x1F619) // 😙
|
||||
);
|
||||
```
|
||||
|
||||
To use it, call `qk_ucis_start()`, then type "rofl" and hit Enter. QMK should erase the "rofl" text and insert the laughing emoji.
|
||||
To use it, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl"), and hit Space or Enter. QMK should erase the "rofl" text and insert the laughing emoji.
|
||||
|
||||
### Customization
|
||||
|
||||
@@ -68,7 +90,7 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort
|
||||
|
||||
The following input modes are available:
|
||||
|
||||
* **`UC_OSX`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with `UNICODEMAP`).
|
||||
* **`UC_OSX`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map).
|
||||
|
||||
To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.
|
||||
By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_OSX`](#input-key-configuration) with another keycode.
|
||||
@@ -112,7 +134,7 @@ You can also switch the input mode by calling `set_unicode_input_mode(x)` in you
|
||||
|
||||
```c
|
||||
void eeconfig_init_user(void) {
|
||||
set_unicode_input_mode(UC_LNX);
|
||||
set_unicode_input_mode(UC_LNX);
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -30,6 +30,7 @@ QMK has a staggering number of features for building your keyboard. It can take
|
||||
* [RGB Light](feature_rgblight.md) - RGB lighting for your keyboard.
|
||||
* [RGB Matrix](feature_rgb_matrix.md) - RGB Matrix lights for per key lighting.
|
||||
* [Space Cadet](feature_space_cadet.md) - Use your left/right shift keys to type parenthesis and brackets.
|
||||
* [Split Keyboard](feature_split_keyboard.md)
|
||||
* [Stenography](feature_stenography.md) - Put your keyboard into Plover mode for stenography use.
|
||||
* [Swap Hands](feature_swap_hands.md) - Mirror your keyboard for one handed usage.
|
||||
* [Tap Dance](feature_tap_dance.md) - Make a single key do as many things as you want.
|
||||
|
@@ -119,6 +119,31 @@ Flashing sequence:
|
||||
3. Flash a .hex file
|
||||
4. Reset the device into application mode (may be done automatically)
|
||||
|
||||
## USBasploader
|
||||
|
||||
USBasploader is a bootloader developed by matrixstorm. It is used in some non-USB AVR chips such as the ATmega328P, which run V-USB.
|
||||
|
||||
To ensure compatibility with the USBasploader bootloader, make sure this block is present in your `rules.mk`:
|
||||
|
||||
# Bootloader
|
||||
# This definition is optional, and if your keyboard supports multiple bootloaders of
|
||||
# different sizes, comment this out, and the correct address will be loaded
|
||||
# automatically (+60). See bootloader.mk for all options.
|
||||
BOOTLOADER = USBasp
|
||||
|
||||
Compatible flashers:
|
||||
|
||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
||||
* [avrdude](http://www.nongnu.org/avrdude/) with the `usbasp` programmer
|
||||
* [AVRDUDESS](https://github.com/zkemble/AVRDUDESS)
|
||||
|
||||
Flashing sequence:
|
||||
|
||||
1. Press the `RESET` keycode, or keep the boot pin shorted to GND while quickly shorting RST to GND
|
||||
2. Wait for the OS to detect the device
|
||||
3. Flash a .hex file
|
||||
4. Reset the device into application mode (may be done automatically)
|
||||
|
||||
## STM32
|
||||
|
||||
All STM32 chips come preloaded with a factory bootloader that cannot be modified nor deleted. Some STM32 chips have bootloaders that do not come with USB programming (e.g. STM32F103) but the process is still the same.
|
||||
|
@@ -83,7 +83,7 @@ This allows the keyboard to tell the host OS that up to 248 keys are held down a
|
||||
|
||||
`BACKLIGHT_ENABLE`
|
||||
|
||||
This enables your backlight on Timer1 and ports B5, B6, or B7 (for now). You can specify your port by putting this in your `config.h`:
|
||||
This enables the in-switch LED backlighting. You can specify the backlight pin by putting this in your `config.h`:
|
||||
|
||||
#define BACKLIGHT_PIN B7
|
||||
|
||||
|
@@ -1,16 +1,20 @@
|
||||
# Vagrant Quick Start
|
||||
|
||||
This project includes a Vagrantfile that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
|
||||
This project includes a `Vagrantfile` that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
|
||||
|
||||
## Requirements
|
||||
|
||||
Using the `/Vagrantfile` in this repository requires you have [Vagrant](http://www.vagrantup.com/) as well as [VirtualBox](https://www.virtualbox.org/) (or [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](http://www.vagrantup.com/vmware) but the (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion).
|
||||
Using the `Vagrantfile` in this repository requires you have [Vagrant](http://www.vagrantup.com/) as well as a supported provider installed:
|
||||
|
||||
*COMPATIBILITY NOTICE* Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12. **Alternately, you can try running the following command:** `vagrant plugin install vagrant-vbguest`
|
||||
* [VirtualBox](https://www.virtualbox.org/) (Version at least 5.0.12)
|
||||
* Sold as 'the most accessible platform to use Vagrant'
|
||||
* [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](http://www.vagrantup.com/vmware)
|
||||
* The (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion
|
||||
* [Docker](https://www.docker.com/)
|
||||
|
||||
Other than having Vagrant and Virtualbox installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start a Linux virtual machine that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
|
||||
Other than having Vagrant, a suitable provider installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start an environment (either a virtual machine or container) that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
|
||||
|
||||
# Flashing the Firmware
|
||||
## Flashing the Firmware
|
||||
|
||||
The "easy" way to flash the firmware is using a tool from your host OS:
|
||||
|
||||
@@ -19,3 +23,35 @@ The "easy" way to flash the firmware is using a tool from your host OS:
|
||||
* [Atmel FLIP](http://www.atmel.com/tools/flip.aspx)
|
||||
|
||||
If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.
|
||||
|
||||
## Vagrantfile Overview
|
||||
The development environment is configured to run the QMK Docker image, `qmkfm/base_container`. This not only ensures predictability between systems, it also mirrors the CI environment.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why am I seeing issues under Virtualbox?
|
||||
Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12. **Alternately, you can try running the following command:**
|
||||
|
||||
```console
|
||||
vagrant plugin install vagrant-vbguest
|
||||
```
|
||||
|
||||
### How do I remove an existing environment?
|
||||
Finished with your environment? From anywhere inside the folder where you checked out this project, Execute:
|
||||
|
||||
```console
|
||||
vagrant destory
|
||||
```
|
||||
|
||||
### What if I want to use Docker directly?
|
||||
Want to benefit from the Vagrant workflow without a virtual machine? The Vagrantfile is configured to bypass running a virtual machine, and run the container directly. Execute the following when bringing up the environment to force the use of Docker:
|
||||
```console
|
||||
vagrant up --provider=docker
|
||||
```
|
||||
|
||||
### How do I access the virtual machine instead of the Docker container?
|
||||
Execute the following to bypass the `vagrant` user booting directly to the official qmk builder image:
|
||||
|
||||
```console
|
||||
vagrant ssh -c 'sudo -i'
|
||||
```
|
@@ -125,7 +125,7 @@ To configure a keyboard where each switch is connected to a separate pin and gro
|
||||
|
||||
### Backlight Configuration
|
||||
|
||||
By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are using one of those you can simply enable it here. For more details see the [Backlight Documentation](feature_backlight.md).
|
||||
QMK supports backlighting on most GPIO pins. A select few of these can be driven by the MCU in hardware. For more details see the [Backlight Documentation](feature_backlight.md).
|
||||
|
||||
```c
|
||||
#define BACKLIGHT_PIN B7
|
||||
@@ -134,8 +134,6 @@ By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are us
|
||||
#define BREATHING_PERIOD 6
|
||||
```
|
||||
|
||||
?> You can use backlighting on any pin you like, but you will have to do more work to support that. See the [Backlight Documentation](feature_backlight.md) for more details.
|
||||
|
||||
### Other Configuration Options
|
||||
|
||||
There are a lot of features that can be configured or tuned in `config.h`. You should see the [Config Options](config_options.md) page for more details.
|
||||
|
@@ -73,7 +73,22 @@ STM32 MCUs allows a variety of pins to be configured as I2C pins depending on th
|
||||
| `I2C1_SDA` | The pin number for the SDA pin (0-9) | `7` |
|
||||
| `I2C1_BANK` (deprecated) | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`), superceded by `I2C1_SCL_BANK`, `I2C1_SDA_BANK` | `GPIOB` |
|
||||
|
||||
STM32 MCUs allow for different timing parameters when configuring I2C. These can be modified using the following parameters, using https://www.st.com/en/embedded-software/stsw-stm32126.html as a reference:
|
||||
The ChibiOS I2C driver configuration depends on STM32 MCU:
|
||||
|
||||
STM32F1xx, STM32F2xx, STM32F4xx, STM32L0xx and STM32L1xx use I2Cv1;
|
||||
STM32F0xx, STM32F3xx, STM32F7xx and STM32L4xx use I2Cv2;
|
||||
|
||||
#### I2Cv1
|
||||
STM32 MCUs allow for different clock and duty parameters when configuring I2Cv1. These can be modified using the following parameters, using <https://www.playembedded.org/blog/stm32-i2c-chibios/#I2Cv1_configuration_structure> as a reference:
|
||||
|
||||
| Variable | Default |
|
||||
|--------------------|------------------|
|
||||
| `I2C1_OPMODE` | `OPMODE_I2C` |
|
||||
| `I2C1_CLOCK_SPEED` | `100000` |
|
||||
| `I2C1_DUTY_CYCLE` | `STD_DUTY_CYCLE` |
|
||||
|
||||
#### I2Cv2
|
||||
STM32 MCUs allow for different timing parameters when configuring I2Cv2. These can be modified using the following parameters, using <https://www.st.com/en/embedded-software/stsw-stm32126.html> as a reference:
|
||||
|
||||
| Variable | Default |
|
||||
|-----------------------|---------|
|
||||
@@ -83,13 +98,14 @@ STM32 MCUs allow for different timing parameters when configuring I2C. These can
|
||||
| `I2C1_TIMINGR_SCLH` | `15U` |
|
||||
| `I2C1_TIMINGR_SCLL` | `21U` |
|
||||
|
||||
STM32 MCUs allow for different "alternate function" modes when configuring GPIO pins. These are required to switch the pins used to I2C mode. See the respective datasheet for the appropriate values for your MCU.
|
||||
STM32 MCUs allow for different "alternate function" modes when configuring GPIO pins. These are required to switch the pins used to I2Cv2 mode. See the respective datasheet for the appropriate values for your MCU.
|
||||
|
||||
| Variable | Default |
|
||||
|---------------------|---------|
|
||||
| `I2C1_SCL_PAL_MODE` | `4` |
|
||||
| `I2C1_SDA_PAL_MODE` | `4` |
|
||||
|
||||
#### Other
|
||||
You can also overload the `void i2c_init(void)` function, which has a weak attribute. If you do this the configuration variables above will not be used. Please consult the datasheet of your MCU for the available GPIO configurations. The following is an example initialization function:
|
||||
|
||||
```C
|
||||
|
@@ -4,7 +4,7 @@ The [QMK Configurator](https://config.qmk.fm) is an online graphical user interf
|
||||
|
||||
?> **Please follow these steps in order.**
|
||||
|
||||
Watch the [Video Tutorial](https://youtu.be/7RH-1pAbjvw)
|
||||
Watch the [Video Tutorial](https://youtu.be/tx54jkRC9ZY)
|
||||
|
||||
The QMK Configurator works best with Chrome/Firefox.
|
||||
|
||||
|
@@ -127,9 +127,7 @@ Once it does this, you'll want to reset the controller. It should then show out
|
||||
>>> dfu-programmer atmega32u4 reset
|
||||
```
|
||||
|
||||
If you have any issues with this, you may need to this:
|
||||
|
||||
sudo make <my_keyboard>:<my_keymap>:dfu
|
||||
?> If you have any issues with this - such as `dfu-programmer: no device present` - please see the [Frequently Asked Build Questions](faq_build.md).
|
||||
|
||||
#### DFU commands
|
||||
|
||||
@@ -225,7 +223,7 @@ For the PJRC devices (Teensy's), when you're ready to compile and flash your fir
|
||||
|
||||
For example, if your keymap is named "xyverz" and you're building a keymap for an Ergodox or Ergodox EZ, you'll use this command:
|
||||
|
||||
make erdogox_ez:xyverz:teensy
|
||||
make ergodox_ez:xyverz:teensy
|
||||
|
||||
Once the firmware finishes compiling, it will output something like this:
|
||||
|
||||
|
@@ -34,7 +34,7 @@ For the `DIODE_DIRECTION`, most hand-wiring guides will instruct you to wire the
|
||||
|
||||
To configure a keyboard where each switch is connected to a separate pin and ground instead of sharing row and column pins, use `DIRECT_PINS`. The mapping defines the pins of each switch in rows and columns, from left to right. Must conform to the sizes within `MATRIX_ROWS` and `MATRIX_COLS`, use `NO_PIN` to fill in blank spaces. Overrides the behaviour of `DIODE_DIRECTION`, `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`.
|
||||
|
||||
`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to. Currently only B5, B6, and B7 are supported.
|
||||
`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to.
|
||||
|
||||
`BACKLIGHT_BREATHING` is a fancier backlight feature that adds breathing/pulsing/fading effects to the backlight. It uses the same timer as the normal backlight. These breathing effects must be called by code in your keymap.
|
||||
|
||||
|
45
docs/python_development.md
Normal file
45
docs/python_development.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Python Development in QMK
|
||||
|
||||
This document gives an overview of how QMK has structured its python code. You should read this before working on any of the python code.
|
||||
|
||||
## Script directories
|
||||
|
||||
There are two places scripts live in QMK: `qmk_firmware/bin` and `qmk_firmware/util`. You should use `bin` for any python scripts that utilize the `qmk` wrapper. Scripts that are standalone and not run very often live in `util`.
|
||||
|
||||
We discourage putting anything into `bin` that does not utilize the `qmk` wrapper. If you think you have a good reason for doing so please talk to us about your use case.
|
||||
|
||||
## Python Modules
|
||||
|
||||
Most of the QMK python modules can be found in `qmk_firmware/lib/python`. This is the path that we append to `sys.path`.
|
||||
|
||||
We have a module hierarchy under that path:
|
||||
|
||||
* `qmk_firmware/lib/python`
|
||||
* `milc.py` - The CLI library we use. Will be pulled out into its own module in the future.
|
||||
* `qmk` - Code associated with QMK
|
||||
* `cli` - Modules that will be imported for CLI commands.
|
||||
* `errors.py` - Errors that can be raised within QMK apps
|
||||
* `keymap.py` - Functions for working with keymaps
|
||||
|
||||
## CLI Scripts
|
||||
|
||||
We have a CLI wrapper that you should utilize for any user facing scripts. We think it's pretty easy to use and it gives you a lot of nice things for free.
|
||||
|
||||
To use the wrapper simply place a module into `qmk_firmware/lib/python/qmk/cli`, and create a symlink to `bin/qmk` named after your module. Dashes in command names will be converted into dots so you can use hierarchy to manage commands.
|
||||
|
||||
When `qmk` is run it checks to see how it was invoked. If it was invoked as `qmk` the module name is take from `sys.argv[1]`. If it was invoked as `qmk-<module-name>` then everything after the first dash is taken as the module name. Dashes and underscores are converted to dots, and then `qmk.cli` is prepended before the module is imported.
|
||||
|
||||
The module uses `@cli.entrypoint()` and `@cli.argument()` decorators to define an entrypoint, which is where execution starts.
|
||||
|
||||
## Example CLI Script
|
||||
|
||||
We have provided a QMK Hello World script you can use as an example. To run it simply run `qmk hello` or `qmk-hello`. The source code is listed below.
|
||||
|
||||
```
|
||||
from milc import cli
|
||||
|
||||
@cli.argument('-n', '--name', default='World', help='Name to greet.')
|
||||
@cli.entrypoint('QMK Python Hello World.')
|
||||
def main(cli):
|
||||
cli.echo('Hello, %s!', cli.config.general.name)
|
||||
```
|
@@ -33,11 +33,17 @@
|
||||
static uint8_t i2c_address;
|
||||
|
||||
static const I2CConfig i2cconfig = {
|
||||
#ifdef USE_I2CV1
|
||||
I2C1_OPMODE,
|
||||
I2C1_CLOCK_SPEED,
|
||||
I2C1_DUTY_CYCLE,
|
||||
#else
|
||||
STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) |
|
||||
STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) |
|
||||
STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL),
|
||||
0,
|
||||
0
|
||||
#endif
|
||||
};
|
||||
|
||||
static i2c_status_t chibios_to_qmk(const msg_t* status) {
|
||||
@@ -61,8 +67,13 @@ void i2c_init(void)
|
||||
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
#ifdef USE_I2CV1
|
||||
palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
|
||||
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
|
||||
#else
|
||||
palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
#endif
|
||||
|
||||
//i2cInit(); //This is invoked by halInit() so no need to redo it.
|
||||
}
|
||||
@@ -106,11 +117,11 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
|
||||
{
|
||||
i2c_address = devaddr;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), regaddr, 1, data, length, MS2ST(timeout));
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, MS2ST(timeout));
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
|
@@ -22,10 +22,16 @@
|
||||
* Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
|
||||
* STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ch.h"
|
||||
#include <hal.h>
|
||||
|
||||
|
||||
#if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32L0xx) || defined(STM32L1xx)
|
||||
#define USE_I2CV1
|
||||
#endif
|
||||
|
||||
#ifdef I2C1_BANK
|
||||
#define I2C1_SCL_BANK I2C1_BANK
|
||||
#define I2C1_SDA_BANK I2C1_BANK
|
||||
@@ -46,30 +52,42 @@
|
||||
#define I2C1_SDA 7
|
||||
#endif
|
||||
|
||||
// The default PAL alternate modes are used to signal that the pins are used for I2C
|
||||
#ifndef I2C1_SCL_PAL_MODE
|
||||
#define I2C1_SCL_PAL_MODE 4
|
||||
#endif
|
||||
#ifndef I2C1_SDA_PAL_MODE
|
||||
#define I2C1_SDA_PAL_MODE 4
|
||||
#endif
|
||||
#ifdef USE_I2CV1
|
||||
#ifndef I2C1_OPMODE
|
||||
#define I2C1_OPMODE OPMODE_I2C
|
||||
#endif
|
||||
#ifndef I2C1_CLOCK_SPEED
|
||||
#define I2C1_CLOCK_SPEED 100000 /* 400000 */
|
||||
#endif
|
||||
#ifndef I2C1_DUTY_CYCLE
|
||||
#define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */
|
||||
#endif
|
||||
#else
|
||||
// The default PAL alternate modes are used to signal that the pins are used for I2C
|
||||
#ifndef I2C1_SCL_PAL_MODE
|
||||
#define I2C1_SCL_PAL_MODE 4
|
||||
#endif
|
||||
#ifndef I2C1_SDA_PAL_MODE
|
||||
#define I2C1_SDA_PAL_MODE 4
|
||||
#endif
|
||||
|
||||
// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
#ifndef I2C1_TIMINGR_PRESC
|
||||
#define I2C1_TIMINGR_PRESC 15U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLDEL
|
||||
#define I2C1_TIMINGR_SCLDEL 4U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SDADEL
|
||||
#define I2C1_TIMINGR_SDADEL 2U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLH
|
||||
#define I2C1_TIMINGR_SCLH 15U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLL
|
||||
#define I2C1_TIMINGR_SCLL 21U
|
||||
// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
#ifndef I2C1_TIMINGR_PRESC
|
||||
#define I2C1_TIMINGR_PRESC 15U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLDEL
|
||||
#define I2C1_TIMINGR_SCLDEL 4U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SDADEL
|
||||
#define I2C1_TIMINGR_SDADEL 2U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLH
|
||||
#define I2C1_TIMINGR_SCLH 15U
|
||||
#endif
|
||||
#ifndef I2C1_TIMINGR_SCLL
|
||||
#define I2C1_TIMINGR_SCLL 21U
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef I2C_DRIVER
|
||||
@@ -88,5 +106,5 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length);
|
||||
i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
void i2c_stop(void);
|
||||
|
@@ -1,3 +1,18 @@
|
||||
/* Copyright (C) 2019 Elia Ritterbusch
|
||||
+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Library made by: g4lvanix
|
||||
* Github repository: https://github.com/g4lvanix/I2C-master-lib
|
||||
*/
|
||||
|
@@ -1,3 +1,18 @@
|
||||
/* Copyright (C) 2019 Elia Ritterbusch
|
||||
+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Library made by: g4lvanix
|
||||
* Github repository: https://github.com/g4lvanix/I2C-master-lib
|
||||
*/
|
||||
|
@@ -1,3 +1,18 @@
|
||||
/* Copyright (C) 2019 Elia Ritterbusch
|
||||
+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Library made by: g4lvanix
|
||||
* Github repository: https://github.com/g4lvanix/I2C-slave-lib
|
||||
*/
|
||||
@@ -68,4 +83,4 @@ ISR(TWI_vect){
|
||||
|
||||
// Reset i2c state machine to be ready for next interrupt
|
||||
TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,18 @@
|
||||
/* Copyright (C) 2019 Elia Ritterbusch
|
||||
+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Library made by: g4lvanix
|
||||
* Github repository: https://github.com/g4lvanix/I2C-slave-lib
|
||||
|
||||
@@ -15,4 +30,4 @@ extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
|
||||
void i2c_slave_init(uint8_t address);
|
||||
void i2c_slave_stop(void);
|
||||
|
||||
#endif // I2C_SLAVE_H
|
||||
#endif // I2C_SLAVE_H
|
||||
|
@@ -71,10 +71,10 @@ uint8_t g_twi_transfer_buffer[20];
|
||||
// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[DRIVER_COUNT][144];
|
||||
bool g_pwm_buffer_update_required = false;
|
||||
bool g_pwm_buffer_update_required[DRIVER_COUNT] = { false };
|
||||
|
||||
uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } };
|
||||
bool g_led_control_registers_update_required = false;
|
||||
bool g_led_control_registers_update_required[DRIVER_COUNT] = { false };
|
||||
|
||||
// This is the bit pattern in the LED control registers
|
||||
// (for matrix A, add one to register for matrix B)
|
||||
@@ -204,7 +204,7 @@ void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
|
||||
g_pwm_buffer[led.driver][led.r - 0x24] = red;
|
||||
g_pwm_buffer[led.driver][led.g - 0x24] = green;
|
||||
g_pwm_buffer[led.driver][led.b - 0x24] = blue;
|
||||
g_pwm_buffer_update_required = true;
|
||||
g_pwm_buffer_update_required[led.driver] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,12 +220,12 @@ void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, b
|
||||
{
|
||||
is31_led led = g_is31_leds[index];
|
||||
|
||||
uint8_t control_register_r = (led.r - 0x24) / 8;
|
||||
uint8_t control_register_g = (led.g - 0x24) / 8;
|
||||
uint8_t control_register_b = (led.b - 0x24) / 8;
|
||||
uint8_t bit_r = (led.r - 0x24) % 8;
|
||||
uint8_t bit_g = (led.g - 0x24) % 8;
|
||||
uint8_t bit_b = (led.b - 0x24) % 8;
|
||||
uint8_t control_register_r = (led.r - 0x24) / 8;
|
||||
uint8_t control_register_g = (led.g - 0x24) / 8;
|
||||
uint8_t control_register_b = (led.b - 0x24) / 8;
|
||||
uint8_t bit_r = (led.r - 0x24) % 8;
|
||||
uint8_t bit_g = (led.g - 0x24) % 8;
|
||||
uint8_t bit_b = (led.b - 0x24) % 8;
|
||||
|
||||
if ( red ) {
|
||||
g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
|
||||
@@ -243,28 +243,26 @@ void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, b
|
||||
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
|
||||
}
|
||||
|
||||
g_led_control_registers_update_required = true;
|
||||
g_led_control_registers_update_required[led.driver] = true;
|
||||
|
||||
}
|
||||
|
||||
void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
|
||||
void IS31FL3731_update_pwm_buffers( uint8_t addr, uint8_t index )
|
||||
{
|
||||
if ( g_pwm_buffer_update_required )
|
||||
if ( g_pwm_buffer_update_required[index] )
|
||||
{
|
||||
IS31FL3731_write_pwm_buffer( addr1, g_pwm_buffer[0] );
|
||||
IS31FL3731_write_pwm_buffer( addr2, g_pwm_buffer[1] );
|
||||
IS31FL3731_write_pwm_buffer( addr, g_pwm_buffer[index] );
|
||||
}
|
||||
g_pwm_buffer_update_required = false;
|
||||
g_pwm_buffer_update_required[index] = false;
|
||||
}
|
||||
|
||||
void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
|
||||
void IS31FL3731_update_led_control_registers( uint8_t addr, uint8_t index )
|
||||
{
|
||||
if ( g_led_control_registers_update_required )
|
||||
if ( g_led_control_registers_update_required[index] )
|
||||
{
|
||||
for ( int i=0; i<18; i++ )
|
||||
{
|
||||
IS31FL3731_write_register(addr1, i, g_led_control_registers[0][i] );
|
||||
IS31FL3731_write_register(addr2, i, g_led_control_registers[1][i] );
|
||||
IS31FL3731_write_register( addr, i, g_led_control_registers[index][i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -44,8 +44,8 @@ void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, b
|
||||
// (eg. from a timer interrupt).
|
||||
// Call this while idle (in between matrix scans).
|
||||
// If the buffer is dirty, it will update the driver with the buffer.
|
||||
void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
|
||||
void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
|
||||
void IS31FL3731_update_pwm_buffers( uint8_t addr, uint8_t index );
|
||||
void IS31FL3731_update_led_control_registers( uint8_t addr, uint8_t index );
|
||||
|
||||
#define C1_1 0x24
|
||||
#define C1_2 0x25
|
||||
|
@@ -321,7 +321,7 @@ void oled_render(void) {
|
||||
|
||||
// Send render data chunk after rotating
|
||||
if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) {
|
||||
print("oled_render data failed\n");
|
||||
print("oled_render90 data failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -393,6 +393,11 @@ void oled_write_char(const char data, bool invert) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == '\r') {
|
||||
oled_advance_page(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the current render buffer to check for dirty after
|
||||
static uint8_t oled_temp_buffer[OLED_FONT_WIDTH];
|
||||
memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH);
|
||||
|
@@ -17,6 +17,19 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Qwerty
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | Backspace |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | \ |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Caps | A | S | D | F | G | H | J | K | L | ; | ' | Enter |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Shift | Z | X | C | V | B | N | M | , | . | / | Shift |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Ctrl | GUI | Alt | Space | Alt | GUI | L1 | Ctrl |
|
||||
* `-----------------------------------------------------------------------------------------'
|
||||
*/
|
||||
[0] = LAYOUT_60_ansi(
|
||||
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
|
||||
@@ -25,6 +38,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(1), KC_RCTL
|
||||
),
|
||||
|
||||
/* Function
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | ` | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | Del |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | Up | | | | | | | |PrtSc|ScrLk|Pause| |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | |Left |Down |Right| | | | | | Ins |Home |PgUp | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | |VolUp|VolDn|VolMu| | | | | | End |PgDn | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | L2 | | |
|
||||
* `-----------------------------------------------------------------------------------------'
|
||||
*/
|
||||
[1] = LAYOUT_60_ansi(
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
|
||||
KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_TRNS,
|
||||
@@ -33,6 +59,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(2), KC_TRNS, KC_TRNS
|
||||
),
|
||||
|
||||
/* RGB
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | | | | | | | | | | | | | | Reset |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | BL Tog |BLInc|BLDec|BLStp| | | | | | | | | | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | RGB Tog |Mode |Hue I|Sat I|Val I|Spd I|Plain|Breat|Rnbow|Swirl| | | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | |RMode|Hue D|Sat D|Val D|Spd D|Snake|Knigh|Xmas |Gradi| | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | | | |
|
||||
* `-----------------------------------------------------------------------------------------'
|
||||
*/
|
||||
[2] = LAYOUT_60_ansi(
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET,
|
||||
BL_TOGG, BL_INC, BL_DEC, BL_STEP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2018 Jack Humbert
|
||||
/* Copyright 2018 Chuck "@vosechu" Lauer Vose
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,8 +14,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
#pragma once
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = {{ KC_A }}
|
||||
};
|
||||
// place overrides here
|
46
keyboards/1upkeyboards/1up60hse/keymaps/vosechu/keymap.c
Normal file
46
keyboards/1upkeyboards/1up60hse/keymaps/vosechu/keymap.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Copyright 2018 Chuck "@vosechu" Lauer Vose
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
#define SPACEFN LT(1, KC_SPC)
|
||||
#define CTL_GRV CTL_T(KC_GRV)
|
||||
#define ALT_TAB ALT_T(KC_TAB)
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT_60_ansi(
|
||||
KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS , KC_EQL , KC_BSPC ,
|
||||
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC , KC_RBRC , KC_BSLS ,
|
||||
KC_CAPS , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN , KC_QUOT , KC_ENT ,
|
||||
KC_LSFT , KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH , KC_RSFT ,
|
||||
CTL_GRV , ALT_TAB , KC_LGUI , SPACEFN , KC_RALT , KC_RGUI , MO(1) , KC_RCTL
|
||||
),
|
||||
|
||||
[1] = LAYOUT_60_ansi(
|
||||
KC_GRV , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , KC_DEL ,
|
||||
KC_TRNS , KC_TRNS , KC_UP , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_PSCR , KC_SLCK , KC_PAUS , KC_TRNS ,
|
||||
KC_TRNS , KC_LEFT , KC_DOWN , KC_RGHT , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_INS , KC_HOME , KC_PGUP , KC_TRNS ,
|
||||
KC_TRNS , KC_VOLU , KC_VOLD , KC_MUTE , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_END , KC_PGDN , KC_TRNS ,
|
||||
KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , MO(2) , KC_TRNS , KC_TRNS
|
||||
),
|
||||
|
||||
[2] = LAYOUT_60_ansi(
|
||||
KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , RESET ,
|
||||
BL_TOGG , BL_INC , BL_DEC , BL_STEP , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS ,
|
||||
RGB_TOG , RGB_MOD , RGB_HUI , RGB_SAI , RGB_VAI , RGB_SPI , RGB_M_P , RGB_M_B , RGB_M_R , RGB_M_SW , KC_TRNS , KC_TRNS , KC_TRNS ,
|
||||
KC_TRNS , RGB_RMOD , RGB_HUD , RGB_SAD , RGB_VAD , RGB_SPD , RGB_M_SN , RGB_M_K , RGB_M_X , RGB_M_G , KC_TRNS , KC_TRNS ,
|
||||
KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS , KC_TRNS
|
||||
)
|
||||
};
|
@@ -0,0 +1,6 @@
|
||||
# 1up60hse keymap made by vosechu
|
||||
|
||||
Tweaks from default
|
||||
|
||||
* Add in SpaceFN so arrows are reachable with just left hand (leaving right free for mousing).
|
||||
* Also add tab/grv under the alt/ctrl keys to make those easier to reach.
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -18,15 +18,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
};
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
||||
;
|
||||
|
||||
switch (id) {
|
||||
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
void matrix_init_user(void) {
|
||||
}
|
||||
|
||||
|
@@ -18,15 +18,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
};
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
||||
;
|
||||
|
||||
switch (id) {
|
||||
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
void matrix_init_user(void) {
|
||||
}
|
||||
|
||||
|
@@ -18,15 +18,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
};
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
|
||||
;
|
||||
|
||||
switch (id) {
|
||||
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
void matrix_init_user(void) {
|
||||
}
|
||||
|
||||
|
16
keyboards/2_milk/2_milk.c
Normal file
16
keyboards/2_milk/2_milk.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2019 Sebastian Williams
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "2_milk.h"
|
26
keyboards/2_milk/2_milk.h
Normal file
26
keyboards/2_milk/2_milk.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2019 Sebastian Williams
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#define LAYOUT( \
|
||||
K00, \
|
||||
K01 \
|
||||
) { \
|
||||
{ K00 }, \
|
||||
{ K01 } \
|
||||
}
|
41
keyboards/2_milk/config.h
Normal file
41
keyboards/2_milk/config.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright 2019 Sebastian Williams
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "config_common.h"
|
||||
|
||||
/* USB Device descriptor parameter */
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0xB195
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER rionlion100
|
||||
#define PRODUCT 2% Milk
|
||||
#define DESCRIPTION A milk themed 2% Keyboard
|
||||
|
||||
/* key matrix size */
|
||||
#define MATRIX_ROWS 2
|
||||
#define MATRIX_COLS 1
|
||||
|
||||
/* Milk default pinout */
|
||||
#define DIRECT_PINS { \
|
||||
{D4}, \
|
||||
{C6} \
|
||||
}
|
||||
#define UNUSED_PINS
|
||||
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
#define RGB_DI_PIN B6
|
||||
#define RGBLED_NUM 1
|
||||
#endif
|
15
keyboards/2_milk/info.json
Normal file
15
keyboards/2_milk/info.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"keyboard_name": "2% Milk",
|
||||
"keyboard_folder": "2_milk",
|
||||
"url": "",
|
||||
"maintainer": "rionlion100",
|
||||
"width": 1,
|
||||
"height": 2,
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"key_count": 2,
|
||||
"layout": [ {"x": 0, "y": 0 }, {"x": 0, "y": 1 }]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
keyboards/2_milk/keymaps/binary/keymap.c
Normal file
8
keyboards/2_milk/keymaps/binary/keymap.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
KC_P0,
|
||||
KC_P1
|
||||
)
|
||||
};
|
2
keyboards/2_milk/keymaps/binary/readme.md
Normal file
2
keyboards/2_milk/keymaps/binary/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Binary keymap
|
||||
0 and 1 that's it
|
9
keyboards/2_milk/keymaps/copypasta/keymap.c
Normal file
9
keyboards/2_milk/keymaps/copypasta/keymap.c
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
RCTL(KC_C),
|
||||
RCTL(KC_V)
|
||||
)
|
||||
};
|
2
keyboards/2_milk/keymaps/copypasta/readme.md
Normal file
2
keyboards/2_milk/keymaps/copypasta/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Copy/Paste Keymap
|
||||

|
8
keyboards/2_milk/keymaps/default/keymap.c
Normal file
8
keyboards/2_milk/keymaps/default/keymap.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
KC_Z,
|
||||
KC_X
|
||||
)
|
||||
};
|
2
keyboards/2_milk/keymaps/default/readme.md
Normal file
2
keyboards/2_milk/keymaps/default/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Default keymap for 2% Milk
|
||||

|
31
keyboards/2_milk/keymaps/emoji/keymap.c
Normal file
31
keyboards/2_milk/keymaps/emoji/keymap.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
enum custom_keycodes {
|
||||
DISSA,
|
||||
SHRUG
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
SHRUG,
|
||||
DISSA
|
||||
)
|
||||
};
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case SHRUG:
|
||||
if (record->event.pressed) {
|
||||
send_unicode_hex_string("00AF 005C 005F 0028 30C4 0029 005F 002F 00AF");
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
case DISSA:
|
||||
if (record->event.pressed) {
|
||||
send_unicode_hex_string("0CA0 005F 0CA0");
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
2
keyboards/2_milk/keymaps/emoji/readme.md
Normal file
2
keyboards/2_milk/keymaps/emoji/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Emoji Keymap
|
||||

|
8
keyboards/2_milk/keymaps/excessbread/keymap.c
Normal file
8
keyboards/2_milk/keymaps/excessbread/keymap.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
KC_LGUI,
|
||||
KC_F11
|
||||
)
|
||||
};
|
2
keyboards/2_milk/keymaps/excessbread/readme.md
Normal file
2
keyboards/2_milk/keymaps/excessbread/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# ExcessBread's keymap
|
||||
requested by excessbread
|
8
keyboards/2_milk/keymaps/mouse/keymap.c
Normal file
8
keyboards/2_milk/keymaps/mouse/keymap.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT(
|
||||
KC_BTN1,
|
||||
KC_BTN2
|
||||
)
|
||||
};
|
2
keyboards/2_milk/keymaps/mouse/readme.md
Normal file
2
keyboards/2_milk/keymaps/mouse/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# left and right mouse buttons
|
||||
requested by WanderingVagrant
|
19
keyboards/2_milk/readme.md
Normal file
19
keyboards/2_milk/readme.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 2% Milk
|
||||
|
||||

|
||||
|
||||
A 2% Meme board themed around a milk carton
|
||||
|
||||
Keyboard Maintainer: [Rionlion100](https://github.com/rionlion100)
|
||||
Hardware Availability: [Open Source](https://github.com/Rionlion100/Spaceboards/tree/master/Keyboards/2%25%20Milk)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make 2_milk:default
|
||||
|
||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||
|
||||
### Credits
|
||||
+ Case design by Soft
|
||||
+ PCB by PyroL
|
||||
+ Name by jetpacktuxedo
|
34
keyboards/2_milk/rules.mk
Normal file
34
keyboards/2_milk/rules.mk
Normal file
@@ -0,0 +1,34 @@
|
||||
# MCU name
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
F_CPU = 16000000
|
||||
|
||||
#
|
||||
# LUFA specific
|
||||
#
|
||||
# Target architecture (see library "Board Types" documentation).
|
||||
ARCH = AVR8
|
||||
|
||||
# Input clock frequency.
|
||||
F_USB = $(F_CPU)
|
||||
|
||||
# Bootloader
|
||||
BOOTLOADER = caterina
|
||||
|
||||
# Interrupt driven control endpoint task(+60)
|
||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
||||
|
||||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
|
||||
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
|
||||
EXTRAKEY_ENABLE = no # Audio control and System control(+450)
|
||||
CONSOLE_ENABLE = yes # Console for debug(+400)
|
||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
||||
BACKLIGHT_ENABLE = no # Custom backlighting code is used, so this should not be enabled
|
||||
AUDIO_ENABLE = no # This can be enabled if a speaker is connected to the expansion port. Not compatible with RGBLIGHT below
|
||||
RGBLIGHT_ENABLE = yes # This can be enabled if a ws2812 strip is connected to the expansion port.
|
@@ -18,46 +18,24 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
};
|
||||
|
||||
void matrix_init_user(void) {
|
||||
}
|
||||
void keyboard_pre_init_user(void) {
|
||||
// Call the keyboard pre init code.
|
||||
|
||||
void matrix_scan_user(void) {
|
||||
}
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
// Set our LED pins as output
|
||||
setPinOutput(D5);
|
||||
setPinOutput(B0);
|
||||
}
|
||||
|
||||
void led_set_user(uint8_t usb_led) {
|
||||
|
||||
if (usb_led & (1 << USB_LED_NUM_LOCK)) {
|
||||
DDRD |= (1 << 5); PORTD &= ~(1 << 5);
|
||||
if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
|
||||
writePinLow(D5);
|
||||
} else {
|
||||
DDRD &= ~(1 << 5); PORTD &= ~(1 << 5);
|
||||
writePinHigh(D5);
|
||||
}
|
||||
|
||||
if (usb_led & (1 << USB_LED_CAPS_LOCK)) {
|
||||
DDRB |= (1 << 0); PORTB &= ~(1 << 0);
|
||||
if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
|
||||
writePinLow(B0);
|
||||
} else {
|
||||
DDRB &= ~(1 << 0); PORTB &= ~(1 << 0);
|
||||
writePinHigh(B0);
|
||||
}
|
||||
|
||||
if (usb_led & (1 << USB_LED_SCROLL_LOCK)) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if (usb_led & (1 << USB_LED_COMPOSE)) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if (usb_led & (1 << USB_LED_KANA)) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
extern keymap_config_t keymap_config;
|
||||
|
||||
// Each layer gets a name for readability, which is then used in the keymap matrix below.
|
||||
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
|
||||
// Layer names don't all need to be of the same length, obviously, and you can also skip them
|
||||
@@ -15,18 +13,18 @@ enum custom_keycodes {
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[_BASE] = LAYOUT_60_ansi(
|
||||
KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
|
||||
KC_LCTL , KC_LGUI , KC_LALT , KC_SPC , KC_RALT , KC_RGUI , MO(_FN1) , KC_RCTL
|
||||
KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
|
||||
KC_LCTL, KC_LGUI, KC_LALT , KC_SPC, KC_RALT, KC_RGUI, MO(_FN1), KC_RCTL
|
||||
),
|
||||
|
||||
[_FN1] = LAYOUT_60_ansi(
|
||||
KC_GESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC, \
|
||||
RGB_TOG, RGB_MOD, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______,\
|
||||
BL_INC, BL_DEC, BL_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
KC_GRV, _______, _______, _______, _______, _______, _______, _______
|
||||
KC_GESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC,
|
||||
RGB_TOG, RGB_MOD, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
BL_INC, BL_DEC, BL_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
KC_GRV, _______, _______, _______, _______, _______, _______, _______
|
||||
)
|
||||
};
|
||||
|
6
keyboards/40percentclub/luddite/keymaps/tzarc/config.h
Normal file
6
keyboards/40percentclub/luddite/keymaps/tzarc/config.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#undef RGBLED_NUM
|
||||
#define RGBLED_NUM 16
|
||||
|
||||
#define QMK_ESC_OUTPUT F4
|
||||
#define QMK_ESC_INPUT D3
|
||||
#define QMK_LED B0
|
30
keyboards/40percentclub/luddite/keymaps/tzarc/keymap.c
Normal file
30
keyboards/40percentclub/luddite/keymaps/tzarc/keymap.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
// Each layer gets a name for readability, which is then used in the keymap matrix below.
|
||||
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
|
||||
// Layer names don't all need to be of the same length, obviously, and you can also skip them
|
||||
// entirely and just use numbers.
|
||||
#define _BASE 0
|
||||
#define _FN1 1
|
||||
|
||||
enum custom_keycodes {
|
||||
QWERTY = SAFE_RANGE,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[_BASE] = LAYOUT_60_ansi(
|
||||
KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
|
||||
KC_LCTL, KC_LGUI, KC_LALT , KC_SPC, KC_RALT, KC_APP, MO(_FN1), KC_RCTL
|
||||
),
|
||||
|
||||
[_FN1] = LAYOUT_60_ansi(
|
||||
KC_GESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,
|
||||
RGB_TOG, RGB_MOD, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
BL_INC, BL_DEC, BL_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
KC_GRV, _______, _______, _______, _______, KC_RGUI, _______, _______
|
||||
)
|
||||
};
|
1
keyboards/40percentclub/luddite/keymaps/tzarc/rules.mk
Normal file
1
keyboards/40percentclub/luddite/keymaps/tzarc/rules.mk
Normal file
@@ -0,0 +1 @@
|
||||
BOOTLOADER = qmk-dfu
|
@@ -3,7 +3,7 @@
|
||||
#include "quantum.h"
|
||||
|
||||
#define LAYOUT_60_ansi( \
|
||||
K00, K01, K02, K03, K04, K05, K06, K07, K10, K11, K12, K13, K14, K15, \
|
||||
K00, K01, K02, K03, K04, K05, K06, K07, K10, K11, K12, K13, K14, K15, \
|
||||
K16, K17, K20, K21, K22, K23, K24, K25, K26, K27, K30, K31, K32, K33, \
|
||||
K34, K35, K36, K37, K40, K41, K42, K43, K44, K45, K46, K47, K50, \
|
||||
K51, K52, K53, K54, K55, K56, K57, K60, K61, K62, K63, K64, \
|
||||
@@ -18,4 +18,3 @@
|
||||
{ K60, K61, K62, K63, K64, K65, K66, K67 }, \
|
||||
{ K70, K71, K72, K73, K74 }, \
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1287
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1287
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -125,11 +125,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* key combination for magic key command */
|
||||
/*#define IS_COMMAND() ( \
|
||||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
|
||||
)*/
|
||||
|
||||
/* control how magic key switches layers */
|
||||
//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
|
||||
//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
|
||||
@@ -239,7 +234,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// #define BOOTMAGIC_LITE_ROW 0
|
||||
// #define BOOTMAGIC_LITE_COLUMN 0
|
||||
|
||||
#define NUMBER_OF_ENCODERS 3
|
||||
#define ENCODERS_PAD_A { B2, B3, D5 }
|
||||
#define ENCODERS_PAD_B { B1, B7, B4 }
|
||||
#define ENCODER_RESOLUTION 2
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1287
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
52
keyboards/ai03/lunar/keymaps/muzfuz/keymap.c
Normal file
52
keyboards/ai03/lunar/keymaps/muzfuz/keymap.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
// Helpful defines
|
||||
#define ESC_CTL CTL_T(KC_ESCAPE) // Tap for Esc, hold for Ctrl
|
||||
#define FL_KCF LT(1,KC_F)
|
||||
#define FL_KCJ LT(1,KC_J)
|
||||
#define CMD_ENT LGUI(LSFT(KC_ENT))
|
||||
|
||||
enum custom_keycodes {
|
||||
HASHRKT = SAFE_RANGE,
|
||||
CLNEQLS,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT( /* Base */
|
||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_BSLS, LGUI(KC_C),
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, LGUI(KC_V),
|
||||
ESC_CTL, KC_A, KC_S, KC_D, FL_KCF, KC_G, KC_H, FL_KCJ, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP,
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_LSFT, KC_UP, KC_PGDN,
|
||||
CMD_ENT, KC_LALT, KC_LGUI, KC_SPC, KC_SPC, KC_SPC, MO(2), KC_GRV, KC_LEFT, KC_DOWN, KC_RGHT
|
||||
),
|
||||
[1] = LAYOUT( /* FL */
|
||||
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_DEL, KC_VOLU,
|
||||
_______, HASHRKT, _______, KC_LCBR, KC_RCBR, _______, _______, KC_UNDS, KC_PLUS, KC_PIPE, _______, _______, _______, _______, KC_VOLD,
|
||||
_______, CLNEQLS, _______, KC_LBRC, KC_RBRC, _______, _______, KC_MINS, KC_EQL, KC_BSLS, KC_TILD, KC_GRV, _______, KC_HOME,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
|
||||
),
|
||||
[2] = LAYOUT( /* FN */
|
||||
RESET, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_DEL, _______,
|
||||
KC_CAPS, _______, KC_UP, _______, _______, _______, KC_NLCK, KC_P7, KC_P8, KC_P9, KC_MPRV, KC_MPLY, KC_MNXT, _______, _______,
|
||||
_______, KC_LEFT, KC_DOWN, KC_RGHT, _______, KC_VOLD, KC_VOLU, KC_P4, KC_P5, KC_P6, _______, _______, _______, _______,
|
||||
_______, KC_RCTL, KC_RGUI, KC_RALT, _______, _______, KC_P0, KC_P1, KC_P2, KC_P3, _______, _______, KC_PGUP, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END
|
||||
)
|
||||
};
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch(keycode) {
|
||||
case HASHRKT:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("=>");
|
||||
}
|
||||
break;
|
||||
case CLNEQLS:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING(":=");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
5
keyboards/ai03/lunar/keymaps/muzfuz/readme.md
Normal file
5
keyboards/ai03/lunar/keymaps/muzfuz/readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# muzfuz's keymap for Lunar
|
||||
|
||||
```shell
|
||||
make ai03/lunar:muzfuz:dfu
|
||||
```
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
@@ -83,4 +82,4 @@ HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
|
||||
SRC += keyboards/wilba_tech/wt_main.c
|
||||
|
||||
RAW_ENABLE = yes
|
||||
DYNAMIC_KEYMAP_ENABLE = yes
|
||||
DYNAMIC_KEYMAP_ENABLE = yes
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -5,7 +5,6 @@ SRC += split_util.c \
|
||||
matrix.c
|
||||
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -23,8 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define PRODUCT_ID 0x6060
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER AKB
|
||||
#define PRODUCT Raine M3
|
||||
#define DESCRIPTION Raine M3
|
||||
#define PRODUCT Raine
|
||||
#define DESCRIPTION Raine
|
||||
|
||||
/* key matrix size */
|
||||
#define MATRIX_ROWS 5
|
||||
|
@@ -68,10 +68,12 @@
|
||||
{ "label": "2", "x": 14.25, "y": 3 },
|
||||
{ "label": "3", "x": 15.25, "y": 3 },
|
||||
{ "label": "Ctrl", "x": 0, "y": 4, "w": 1.25 },
|
||||
{ "label": "Win", "x": 1.25, "y": 4},
|
||||
{ "label": "Alt", "x": 2.25, "y": 4, "w": 1.25 },
|
||||
{ "label": "SPLEFT", "x": 3.5, "y": 4, "w": 2.25 },
|
||||
{ "label": "7U", "x": 5.75, "y": 4 },
|
||||
{ "label": "SPRIGHT", "x": 6.75, "y": 4, "w": 1.75 },
|
||||
{ "label": "alt", "x": 8.5, "y": 4},
|
||||
{ "label": "Menu", "x": 9.5, "y": 4, "w": 1.25 },
|
||||
{ "x": 11, "y": 4.25 },
|
||||
{ "x": 12, "y": 4.25 },
|
||||
|
@@ -17,16 +17,16 @@
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT( /* Base */
|
||||
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_BSPC, KC_NLCK, KC_SLCK, KC_INS,
|
||||
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_BSPC, KC_PSLS, KC_PAST, KC_PPLS,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS, KC_P7, KC_P8, KC_P9,
|
||||
MO(1), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_HASH, KC_ENT, KC_P4, KC_P5, KC_P6,
|
||||
KC_LSFT, KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_SLSH, KC_LSFT, KC_UP, KC_P1, KC_P2, KC_P3,
|
||||
KC_LCTL, KC_LALT, KC_SPC, KC_SPC, KC_SPC, KC_LGUI, KC_LEFT, KC_DOWN, KC_RGHT, KC_P0, KC_DEL),
|
||||
CTL_T(KC_CAPS), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_NUHS, KC_ENT, KC_P4, KC_P5, KC_P6,
|
||||
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_SLSH, KC_RSFT, KC_UP, KC_P1, KC_P2, KC_P3,
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_SPC, KC_BSPC, KC_RALT, MO(1), KC_LEFT, KC_DOWN, KC_RGHT, KC_P0, KC_PDOT),
|
||||
[1] = LAYOUT( /* Second */
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, KC_LBRC, KC_RBRC, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, KC_SCLN, KC_QUOT, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, KC_COMM, KC_DOT, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET),
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_DEL, KC_NLCK, KC_PSCR, KC_INS,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, KC_LBRC, KC_RBRC, _______, KC_HOME, KC_UP, KC_PGUP,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, KC_SCLN, KC_QUOT, _______, _______, KC_LEFT, KC_SLCK, KC_RGHT,
|
||||
_______, _______, _______, _______, _______, _______, _______, KC_COMM, KC_DOT, _______, _______, _______, KC_END, KC_DOWN, KC_PGDN,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET),
|
||||
};
|
||||
|
||||
|
@@ -23,11 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, K113, K114, K115, \
|
||||
K200, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, K213, K214, K215, \
|
||||
K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K311, K312, K313, K314, K315, \
|
||||
K400, K402, K404, K405, K407, K409, K410, K412, K413, K414, K415 \
|
||||
K400, K401, K402, K404, K405, K407, K408, K409, K410, K412, K413, K414, K415 \
|
||||
) { \
|
||||
{ K000, K001, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, K014, K015 }, \
|
||||
{ K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, KC_NO, K113, K114, K115 }, \
|
||||
{ K200, KC_NO, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, K213, K214, K215 }, \
|
||||
{ K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K311, KC_NO, K312, K313, K314, K315 }, \
|
||||
{ K400, KC_NO, K402, KC_NO, K404, K405, KC_NO, K407, KC_NO, K409, K410, KC_NO, K412, K413, K414, K415 } \
|
||||
{ K400, K401, K402, KC_NO, K404, K405, KC_NO, K407, K408, K409, K410, KC_NO, K412, K413, K414, K415 } \
|
||||
}
|
||||
|
@@ -31,23 +31,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPACE, KC_TRNS, KC_RGUI, KC_RCTRL, BL_TOGG, BL_DEC, BL_INC, KC_P0, KC_PDOT ),
|
||||
};
|
||||
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
// MACRODOWN only works in this function
|
||||
switch(id) {
|
||||
case 0:
|
||||
if (record->event.pressed) {
|
||||
register_code(KC_RSFT);
|
||||
} else {
|
||||
unregister_code(KC_RSFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MACRO_NONE;
|
||||
};
|
||||
|
||||
|
||||
void matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
@@ -15,22 +15,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPACE, KC_TRNS, KC_RGUI, KC_RCTRL, BL_TOGG, BL_DEC, BL_INC, KC_P0, KC_PDOT ),
|
||||
};
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
// MACRODOWN only works in this function
|
||||
switch(id) {
|
||||
case 0:
|
||||
if (record->event.pressed) {
|
||||
register_code(KC_RSFT);
|
||||
} else {
|
||||
unregister_code(KC_RSFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MACRO_NONE;
|
||||
};
|
||||
|
||||
|
||||
void matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
@@ -69,4 +68,4 @@ AUDIO_ENABLE = no # Audio output on port C6
|
||||
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
|
||||
|
||||
CUSTOM_MATRIX = yes
|
||||
SRC += matrix.c
|
||||
SRC += matrix.c
|
||||
|
@@ -33,22 +33,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
),
|
||||
};
|
||||
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
// MACRODOWN only works in this function
|
||||
switch(id) {
|
||||
case 0:
|
||||
if (record->event.pressed) {
|
||||
register_code(KC_RSFT);
|
||||
} else {
|
||||
unregister_code(KC_RSFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MACRO_NONE;
|
||||
};
|
||||
|
||||
|
||||
void matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# MCU name
|
||||
#MCU = at90usb1286
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
|
@@ -1,103 +1,112 @@
|
||||
{
|
||||
"keyboard_name": "QMK80",
|
||||
"url": "",
|
||||
"maintainer": "qmk",
|
||||
"width": 18.25,
|
||||
"height": 6.5,
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"key_count": 88,
|
||||
"layout": [
|
||||
{"label":"K00", "x":0, "y":0},
|
||||
{"label":"K01", "x":2, "y":0},
|
||||
{"label":"K02", "x":3, "y":0},
|
||||
{"label":"K03", "x":4, "y":0},
|
||||
{"label":"K04", "x":5, "y":0},
|
||||
{"label":"K05", "x":6.5, "y":0},
|
||||
{"label":"K06", "x":7.5, "y":0},
|
||||
{"label":"K07", "x":8.5, "y":0},
|
||||
{"label":"K08", "x":9.5, "y":0},
|
||||
{"label":"K09", "x":11, "y":0},
|
||||
{"label":"K0A", "x":12, "y":0},
|
||||
{"label":"K0B", "x":13, "y":0},
|
||||
{"label":"K0C", "x":14, "y":0},
|
||||
{"label":"K60", "x":15.25, "y":0},
|
||||
{"label":"K61", "x":16.25, "y":0},
|
||||
{"label":"K62", "x":17.25, "y":0},
|
||||
{"label":"K10", "x":0, "y":1.5},
|
||||
{"label":"K11", "x":1, "y":1.5},
|
||||
{"label":"K12", "x":2, "y":1.5},
|
||||
{"label":"K13", "x":3, "y":1.5},
|
||||
{"label":"K14", "x":4, "y":1.5},
|
||||
{"label":"K15", "x":5, "y":1.5},
|
||||
{"label":"K16", "x":6, "y":1.5},
|
||||
{"label":"K17", "x":7, "y":1.5},
|
||||
{"label":"K18", "x":8, "y":1.5},
|
||||
{"label":"K19", "x":9, "y":1.5},
|
||||
{"label":"K1A", "x":10, "y":1.5},
|
||||
{"label":"K1B", "x":11, "y":1.5},
|
||||
{"label":"K1C", "x":12, "y":1.5},
|
||||
{"label":"K5A", "x":13, "y":1.5, "w":2},
|
||||
{"label":"K63", "x":15.25, "y":1.5},
|
||||
{"label":"K65", "x":16.25, "y":1.5},
|
||||
{"label":"K67", "x":17.25, "y":1.5},
|
||||
{"label":"K20", "x":0, "y":2.5, "w":1.5},
|
||||
{"label":"K21", "x":1.5, "y":2.5},
|
||||
{"label":"K22", "x":2.5, "y":2.5},
|
||||
{"label":"K23", "x":3.5, "y":2.5},
|
||||
{"label":"K24", "x":4.5, "y":2.5},
|
||||
{"label":"K25", "x":5.5, "y":2.5},
|
||||
{"label":"K26", "x":6.5, "y":2.5},
|
||||
{"label":"K27", "x":7.5, "y":2.5},
|
||||
{"label":"K28", "x":8.5, "y":2.5},
|
||||
{"label":"K29", "x":9.5, "y":2.5},
|
||||
{"label":"K2A", "x":10.5, "y":2.5},
|
||||
{"label":"K2B", "x":11.5, "y":2.5},
|
||||
{"label":"K2C", "x":12.5, "y":2.5},
|
||||
{"label":"K4C", "x":13.5, "y":2.5, "w":1.5},
|
||||
{"label":"K64", "x":15.25, "y":2.5},
|
||||
{"label":"K66", "x":16.25, "y":2.5},
|
||||
{"label":"K68", "x":17.25, "y":2.5},
|
||||
{"label":"K30", "x":0, "y":3.5, "w":1.75},
|
||||
{"label":"K31", "x":1.75, "y":3.5},
|
||||
{"label":"K32", "x":2.75, "y":3.5},
|
||||
{"label":"K33", "x":3.75, "y":3.5},
|
||||
{"label":"K34", "x":4.75, "y":3.5},
|
||||
{"label":"K35", "x":5.75, "y":3.5},
|
||||
{"label":"K36", "x":6.75, "y":3.5},
|
||||
{"label":"K37", "x":7.75, "y":3.5},
|
||||
{"label":"K38", "x":8.75, "y":3.5},
|
||||
{"label":"K39", "x":9.75, "y":3.5},
|
||||
{"label":"K3A", "x":10.75, "y":3.5},
|
||||
{"label":"K3B", "x":11.75, "y":3.5},
|
||||
{"label":"K3C", "x":12.75, "y":3.5, "w":2.25},
|
||||
{"label":"K40", "x":0, "y":4.5, "w":2.25},
|
||||
{"label":"K41", "x":2.25, "y":4.5},
|
||||
{"label":"K42", "x":3.25, "y":4.5},
|
||||
{"label":"K43", "x":4.25, "y":4.5},
|
||||
{"label":"K44", "x":5.25, "y":4.5},
|
||||
{"label":"K45", "x":6.25, "y":4.5},
|
||||
{"label":"K46", "x":7.25, "y":4.5},
|
||||
{"label":"K47", "x":8.25, "y":4.5},
|
||||
{"label":"K48", "x":9.25, "y":4.5},
|
||||
{"label":"K49", "x":10.25, "y":4.5},
|
||||
{"label":"K4A", "x":11.25, "y":4.5},
|
||||
{"label":"K4B", "x":12.25, "y":4.5, "w":1.75},
|
||||
{"label":"K69", "x":14, "y":4.5},
|
||||
{"label":"K58", "x":16.25, "y":4.5},
|
||||
{"label":"K50", "x":0, "y":5.5, "w":1.25},
|
||||
{"label":"K51", "x":1.25, "y":5.5, "w":1.25},
|
||||
{"label":"K52", "x":2.5, "y":5.5, "w":1.25},
|
||||
{"label":"K53", "x":3.75, "y":5.5, "w":6.25},
|
||||
{"label":"K54", "x":10, "y":5.5, "w":1.25},
|
||||
{"label":"K55", "x":11.25, "y":5.5, "w":1.25},
|
||||
{"label":"K56", "x":12.5, "y":5.5, "w":1.25},
|
||||
{"label":"K57", "x":13.75, "y":5.5, "w":1.25},
|
||||
{"label":"K6A", "x":15.25, "y":5.5},
|
||||
{"label":"K59", "x":16.25, "y":5.5},
|
||||
{"label":"K6B", "x":17.25, "y":5.5}
|
||||
]
|
||||
}
|
||||
"keyboard_name": "x11",
|
||||
"url": "",
|
||||
"maintainer": "qmk",
|
||||
"width": 18.25,
|
||||
"height": 6.5,
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"key_count": 88,
|
||||
"layout": [
|
||||
{"label":"K00", "x":0, "y":0},
|
||||
{"label":"K01", "x":2, "y":0},
|
||||
{"label":"K02", "x":3, "y":0},
|
||||
{"label":"K03", "x":4, "y":0},
|
||||
{"label":"K04", "x":5, "y":0},
|
||||
{"label":"K05", "x":6.5, "y":0},
|
||||
{"label":"K06", "x":7.5, "y":0},
|
||||
{"label":"K07", "x":8.5, "y":0},
|
||||
{"label":"K08", "x":9.5, "y":0},
|
||||
{"label":"K09", "x":11, "y":0},
|
||||
{"label":"K0A", "x":12, "y":0},
|
||||
{"label":"K0B", "x":13, "y":0},
|
||||
{"label":"K0C", "x":14, "y":0},
|
||||
|
||||
{"label":"K62", "x":15.25, "y":0},
|
||||
{"label":"K61", "x":16.25, "y":0},
|
||||
{"label":"K60", "x":17.25, "y":0},
|
||||
|
||||
{"label":"K10", "x":0, "y":1.5},
|
||||
{"label":"K11", "x":1, "y":1.5},
|
||||
{"label":"K12", "x":2, "y":1.5},
|
||||
{"label":"K13", "x":3, "y":1.5},
|
||||
{"label":"K14", "x":4, "y":1.5},
|
||||
{"label":"K15", "x":5, "y":1.5},
|
||||
{"label":"K16", "x":6, "y":1.5},
|
||||
{"label":"K17", "x":7, "y":1.5},
|
||||
{"label":"K18", "x":8, "y":1.5},
|
||||
{"label":"K19", "x":9, "y":1.5},
|
||||
{"label":"K1A", "x":10, "y":1.5},
|
||||
{"label":"K1B", "x":11, "y":1.5},
|
||||
{"label":"K1C", "x":12, "y":1.5},
|
||||
{"label":"K5A", "x":13, "y":1.5, "w":2},
|
||||
|
||||
{"label":"K63", "x":15.25, "y":1.5},
|
||||
{"label":"K65", "x":16.25, "y":1.5},
|
||||
{"label":"K67", "x":17.25, "y":1.5},
|
||||
|
||||
{"label":"K20", "x":0, "y":2.5, "w":1.5},
|
||||
{"label":"K21", "x":1.5, "y":2.5},
|
||||
{"label":"K22", "x":2.5, "y":2.5},
|
||||
{"label":"K23", "x":3.5, "y":2.5},
|
||||
{"label":"K24", "x":4.5, "y":2.5},
|
||||
{"label":"K25", "x":5.5, "y":2.5},
|
||||
{"label":"K26", "x":6.5, "y":2.5},
|
||||
{"label":"K27", "x":7.5, "y":2.5},
|
||||
{"label":"K28", "x":8.5, "y":2.5},
|
||||
{"label":"K29", "x":9.5, "y":2.5},
|
||||
{"label":"K2A", "x":10.5, "y":2.5},
|
||||
{"label":"K2B", "x":11.5, "y":2.5},
|
||||
{"label":"K2C", "x":12.5, "y":2.5},
|
||||
{"label":"K4C", "x":13.5, "y":2.5, "w":1.5},
|
||||
|
||||
{"label":"K64", "x":15.25, "y":2.5},
|
||||
{"label":"K66", "x":16.25, "y":2.5},
|
||||
{"label":"K68", "x":17.25, "y":2.5},
|
||||
|
||||
{"label":"K30", "x":0, "y":3.5, "w":1.75},
|
||||
{"label":"K31", "x":1.75, "y":3.5},
|
||||
{"label":"K32", "x":2.75, "y":3.5},
|
||||
{"label":"K33", "x":3.75, "y":3.5},
|
||||
{"label":"K34", "x":4.75, "y":3.5},
|
||||
{"label":"K35", "x":5.75, "y":3.5},
|
||||
{"label":"K36", "x":6.75, "y":3.5},
|
||||
{"label":"K37", "x":7.75, "y":3.5},
|
||||
{"label":"K38", "x":8.75, "y":3.5},
|
||||
{"label":"K39", "x":9.75, "y":3.5},
|
||||
{"label":"K3A", "x":10.75, "y":3.5},
|
||||
{"label":"K3B", "x":11.75, "y":3.5},
|
||||
{"label":"K3C", "x":12.75, "y":3.5, "w":2.25},
|
||||
|
||||
{"label":"K40", "x":0, "y":4.5, "w":2.25},
|
||||
{"label":"K41", "x":2.25, "y":4.5},
|
||||
{"label":"K42", "x":3.25, "y":4.5},
|
||||
{"label":"K43", "x":4.25, "y":4.5},
|
||||
{"label":"K44", "x":5.25, "y":4.5},
|
||||
{"label":"K45", "x":6.25, "y":4.5},
|
||||
{"label":"K46", "x":7.25, "y":4.5},
|
||||
{"label":"K47", "x":8.25, "y":4.5},
|
||||
{"label":"K48", "x":9.25, "y":4.5},
|
||||
{"label":"K49", "x":10.25, "y":4.5},
|
||||
{"label":"K4A", "x":11.25, "y":4.5},
|
||||
{"label":"K4B", "x":12.25, "y":4.5, "w":1.75},
|
||||
{"label":"K69", "x":14, "y":4.5},
|
||||
|
||||
{"label":"K58", "x":16.25, "y":4.5},
|
||||
|
||||
{"label":"K50", "x":0, "y":5.5, "w":1.25},
|
||||
{"label":"K51", "x":1.25, "y":5.5, "w":1.25},
|
||||
{"label":"K52", "x":2.5, "y":5.5, "w":1.25},
|
||||
{"label":"K53", "x":3.75, "y":5.5, "w":6.25},
|
||||
{"label":"K54", "x":10, "y":5.5, "w":1.25},
|
||||
{"label":"K55", "x":11.25, "y":5.5, "w":1.25},
|
||||
{"label":"K56", "x":12.5, "y":5.5, "w":1.25},
|
||||
{"label":"K57", "x":13.75, "y":5.5, "w":1.25},
|
||||
|
||||
{"label":"K6A", "x":15.25, "y":5.5},
|
||||
{"label":"K59", "x":16.25, "y":5.5},
|
||||
{"label":"K6B", "x":17.25, "y":5.5}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user