mirror of
https://github.com/zsa/qmk_firmware.git
synced 2026-01-13 17:07:58 +00:00
Compare commits
181 Commits
feat/webus
...
15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fe7d6aea2 | ||
|
|
13e1dd3d53 | ||
|
|
038cef3054 | ||
|
|
52f5c344c4 | ||
|
|
0f319b48e6 | ||
|
|
9620bdbf00 | ||
|
|
52e4c04afd | ||
|
|
05ddbc6b6a | ||
|
|
4ca9256118 | ||
|
|
7c51cd7d99 | ||
|
|
47fa4894bb | ||
|
|
c80f69639b | ||
|
|
1f926d5431 | ||
|
|
0e3739a213 | ||
|
|
afdba6115a | ||
|
|
39c6035657 | ||
|
|
40f08c04c3 | ||
|
|
817720fbdb | ||
|
|
368c2f1cdf | ||
|
|
70cfe93f3e | ||
|
|
e1c12338a1 | ||
|
|
ea6f99e05d | ||
|
|
5400211a9a | ||
|
|
c1d468a5b7 | ||
|
|
2a3cc8e273 | ||
|
|
f832395063 | ||
|
|
4af7cbcc71 | ||
|
|
e54578a89c | ||
|
|
616b97782a | ||
|
|
70ce9e566e | ||
|
|
67d52f67df | ||
|
|
9148b001ff | ||
|
|
cb7d24d95d | ||
|
|
4dc4084c03 | ||
|
|
9ac9fffc9c | ||
|
|
7f07b9d5af | ||
|
|
05ed342709 | ||
|
|
05cbac82e3 | ||
|
|
62c1edc5ac | ||
|
|
a73c258d79 | ||
|
|
a2c458863e | ||
|
|
69542eaa4b | ||
|
|
703f905a72 | ||
|
|
f0fe12e005 | ||
|
|
135e0dfff4 | ||
|
|
c29b1da096 | ||
|
|
dfda3cf71d | ||
|
|
6099a97718 | ||
|
|
fe32c9172d | ||
|
|
860995817f | ||
|
|
53e7452e49 | ||
|
|
74d911b5df | ||
|
|
70d35e8e30 | ||
|
|
ac7de6603c | ||
|
|
f7408111c7 | ||
|
|
15d3efd5d1 | ||
|
|
0bd727cb19 | ||
|
|
4a8aa15634 | ||
|
|
54d6f5d4c5 | ||
|
|
3a14d8874f | ||
|
|
354af71894 | ||
|
|
9a97a0eee9 | ||
|
|
925c43c4c0 | ||
|
|
b3c0f3b0ef | ||
|
|
f3edef8c69 | ||
|
|
40e9813ba2 | ||
|
|
9b8e12814a | ||
|
|
40312b7575 | ||
|
|
91f8f7f69e | ||
|
|
ce0c294dc7 | ||
|
|
bea96d1d84 | ||
|
|
ae96eed205 | ||
|
|
560d1c5385 | ||
|
|
66d4c71b03 | ||
|
|
0a3343aca9 | ||
|
|
a595a1b675 | ||
|
|
d0ee924c9d | ||
|
|
9d1f6c699b | ||
|
|
14e5aab4c7 | ||
|
|
bea75bd84e | ||
|
|
5f57fa478d | ||
|
|
ab799d5628 | ||
|
|
af26d4b1fe | ||
|
|
58567e9003 | ||
|
|
4175e3cbe8 | ||
|
|
f62a4e3ec4 | ||
|
|
618075135d | ||
|
|
fc27898796 | ||
|
|
a14b72580d | ||
|
|
0d893b1143 | ||
|
|
930ab89eee | ||
|
|
e3e2489f86 | ||
|
|
415ab3c96c | ||
|
|
be4771380f | ||
|
|
56dd8cfe48 | ||
|
|
74d3820ff4 | ||
|
|
3f2ea83234 | ||
|
|
7d58ebe288 | ||
|
|
9dbff9f9c8 | ||
|
|
de86a0111a | ||
|
|
42f70cd423 | ||
|
|
66d3ac0b72 | ||
|
|
e3f8f475fe | ||
|
|
1d600f09a8 | ||
|
|
25214378a4 | ||
|
|
2258b09275 | ||
|
|
fede32c9eb | ||
|
|
241982ea6c | ||
|
|
4d97dceac6 | ||
|
|
abc9586c2a | ||
|
|
cd7aba09ee | ||
|
|
ff7a7adbcf | ||
|
|
e079d58b7d | ||
|
|
b198661d18 | ||
|
|
b4dc878501 | ||
|
|
b5a5ce043b | ||
|
|
c2788ef766 | ||
|
|
6ee3b53807 | ||
|
|
97649a2ac4 | ||
|
|
789bdaaf16 | ||
|
|
a935511465 | ||
|
|
e881dfd17e | ||
|
|
8a155fe021 | ||
|
|
e9e9233835 | ||
|
|
e19fa20802 | ||
|
|
6eae35c3c0 | ||
|
|
d978c59b52 | ||
|
|
6e9ddbc2e2 | ||
|
|
93f6749e06 | ||
|
|
da34bddba1 | ||
|
|
9f184ab5da | ||
|
|
d5212f4739 | ||
|
|
aba3108289 | ||
|
|
d5d631691d | ||
|
|
31f8c4eb3a | ||
|
|
a5d07e9656 | ||
|
|
ef314477b3 | ||
|
|
5ad8d221c8 | ||
|
|
200c6bedd1 | ||
|
|
0492378872 | ||
|
|
d179863d2e | ||
|
|
89104e0d2d | ||
|
|
9c70eceec1 | ||
|
|
74d97c7c1d | ||
|
|
6d891bfae9 | ||
|
|
3cb9a24bff | ||
|
|
50f3d2556d | ||
|
|
4a5ec09f61 | ||
|
|
47f2ecb633 | ||
|
|
486290af96 | ||
|
|
b39dbc0342 | ||
|
|
6e2424e658 | ||
|
|
db4445e870 | ||
|
|
9bc4684371 | ||
|
|
128bde1be1 | ||
|
|
ffca0ecd0a | ||
|
|
56443ee486 | ||
|
|
0c67055ae1 | ||
|
|
327a6e0f55 | ||
|
|
2dc509475b | ||
|
|
9d0612cb51 | ||
|
|
e8a922ece3 | ||
|
|
9e42d327ce | ||
|
|
a0c98997af | ||
|
|
ec9f501cfb | ||
|
|
c1ba3aef57 | ||
|
|
4040654edf | ||
|
|
d4a6178b89 | ||
|
|
f82d2aedb5 | ||
|
|
6512732a31 | ||
|
|
d3611fbf64 | ||
|
|
0ec90ce881 | ||
|
|
e85eeeaa53 | ||
|
|
9702d6d82e | ||
|
|
8e5b9f89c6 | ||
|
|
cd9064ac52 | ||
|
|
0caa4264c8 | ||
|
|
9aba563661 | ||
|
|
b2db6db409 | ||
|
|
5784d1ab6c | ||
|
|
97fdecf1dd |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -25,7 +25,7 @@ quantum/version.h
|
||||
CMakeLists.txt
|
||||
cmake-build-debug
|
||||
doxygen/
|
||||
.DS_STORE
|
||||
.DS_Store
|
||||
/util/wsl_downloaded
|
||||
/util/win_downloaded
|
||||
/users/
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -13,4 +13,4 @@
|
||||
url = https://github.com/google/googletest
|
||||
[submodule "lib/lufa"]
|
||||
path = lib/lufa
|
||||
url = https://github.com/qmk/lufa
|
||||
url = https://github.com/zsa/lufa
|
||||
|
||||
13
Makefile
13
Makefile
@@ -371,6 +371,9 @@ define PARSE_KEYBOARD
|
||||
# The same if all was specified
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all),true)
|
||||
$$(eval $$(call PARSE_ALL_KEYMAPS))
|
||||
# List all keymaps for the given keyboard
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,list-keymaps),true)
|
||||
$$(eval $$(call LIST_ALL_KEYMAPS))
|
||||
# Try to match the specified keyamp with the list of known keymaps
|
||||
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(KEYMAPS)),true)
|
||||
$$(eval $$(call PARSE_KEYMAP,$$(MATCHED_ITEM)))
|
||||
@@ -407,6 +410,16 @@ endef
|
||||
# endif
|
||||
# endef
|
||||
|
||||
# Prints a list of all known keymaps for the given keyboard
|
||||
define LIST_ALL_KEYMAPS
|
||||
COMMAND_true_LIST_KEYMAPS := \
|
||||
printf "$$(KEYMAPS)\n";
|
||||
COMMAND_false_LIST_KEYMAPS := \
|
||||
printf "$$(MSG_AVAILABLE_KEYMAPS)\n"; \
|
||||
printf "$$(KEYMAPS)\n";
|
||||
COMMANDS += LIST_KEYMAPS
|
||||
endef
|
||||
|
||||
# $1 Keymap
|
||||
# This is the meat of compiling a keyboard, when entering this, everything is known
|
||||
# keyboard, subproject, and keymap
|
||||
|
||||
88
bin/qmk
88
bin/qmk
@@ -4,10 +4,8 @@
|
||||
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
|
||||
from time import strftime
|
||||
|
||||
# Add the QMK python libs to our path
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
@@ -15,12 +13,8 @@ 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:
|
||||
with open(os.path.join(qmk_dir, 'requirements.txt'), 'r') as fd:
|
||||
for line in fd.readlines():
|
||||
line = line.strip().replace('<', '=').replace('>', '=')
|
||||
|
||||
@@ -32,66 +26,58 @@ with open('requirements.txt', 'r') as fd:
|
||||
|
||||
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.')
|
||||
print('Could not find module %s!', module)
|
||||
print('Please run `pip3 install -r requirements.txt` to install the python dependencies.')
|
||||
exit(255)
|
||||
|
||||
# Figure out our version
|
||||
# TODO(skullydazed/anyone): Find a method that doesn't involve git. This is slow in docker and on windows.
|
||||
command = ['git', 'describe', '--abbrev=6', '--dirty', '--always', '--tags']
|
||||
result = subprocess.run(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
if result.returncode == 0:
|
||||
os.environ['QMK_VERSION'] = 'QMK ' + result.stdout.strip()
|
||||
os.environ['QMK_VERSION'] = result.stdout.strip()
|
||||
else:
|
||||
os.environ['QMK_VERSION'] = 'QMK ' + strftime('%Y-%m-%d-%H:%M:%S')
|
||||
os.environ['QMK_VERSION'] = 'nogit-' + strftime('%Y-%m-%d-%H:%M:%S') + '-dirty'
|
||||
|
||||
# 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')
|
||||
milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}'
|
||||
|
||||
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')
|
||||
|
||||
@milc.cli.entrypoint('QMK Helper Script')
|
||||
def qmk_main(cli):
|
||||
"""The function that gets run when no subcommand is provided.
|
||||
"""
|
||||
cli.print_help()
|
||||
|
||||
|
||||
def main():
|
||||
"""Setup our environment and then call the CLI entrypoint.
|
||||
"""
|
||||
# Change to the root of our checkout
|
||||
os.environ['ORIG_CWD'] = os.getcwd()
|
||||
os.chdir(qmk_dir)
|
||||
|
||||
# Import the subcommands
|
||||
import qmk.cli
|
||||
|
||||
# Execute
|
||||
return_code = milc.cli()
|
||||
|
||||
if return_code is False:
|
||||
exit(1)
|
||||
|
||||
if sys.argv[1] in ['-V', '--version']:
|
||||
milc.cli.echo(os.environ['QMK_VERSION'])
|
||||
exit(0)
|
||||
elif return_code is not True and isinstance(return_code, int):
|
||||
if return_code < 0 or return_code > 255:
|
||||
milc.cli.log.error('Invalid return_code: %d', return_code)
|
||||
exit(255)
|
||||
|
||||
sys.argv[0] = script_name = '-'.join((script_name, sys.argv[1]))
|
||||
del sys.argv[1]
|
||||
exit(return_code)
|
||||
|
||||
# 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()
|
||||
main()
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
qmk
|
||||
@@ -1 +0,0 @@
|
||||
qmk
|
||||
@@ -1 +0,0 @@
|
||||
qmk
|
||||
@@ -1 +0,0 @@
|
||||
qmk
|
||||
@@ -19,12 +19,14 @@
|
||||
#
|
||||
# Sets the bootloader defined in the keyboard's/keymap's rules.mk
|
||||
# Current options:
|
||||
# atmel-dfu
|
||||
# lufa-dfu
|
||||
# qmk-dfu
|
||||
# halfkay
|
||||
# caterina
|
||||
# bootloadHID
|
||||
#
|
||||
# halfkay PJRC Teensy
|
||||
# caterina Pro Micro (Sparkfun/generic)
|
||||
# atmel-dfu Atmel factory DFU
|
||||
# lufa-dfu LUFA DFU
|
||||
# qmk-dfu QMK DFU (LUFA + blinkenlight)
|
||||
# bootloadHID HIDBootFlash compatible (ATmega32A)
|
||||
# USBasp USBaspLoader (ATmega328P)
|
||||
#
|
||||
# BOOTLOADER_SIZE can still be defined manually, but it's recommended
|
||||
# you add any possible configuration to this list
|
||||
@@ -32,40 +34,40 @@
|
||||
ifeq ($(strip $(BOOTLOADER)), atmel-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_ATMEL_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifeq ($(strip $(MCU)), atmega32u4)
|
||||
BOOTLOADER_SIZE = 4096
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
BOOTLOADER_SIZE = 8192
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), lufa-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_LUFA_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifeq ($(strip $(MCU)), atmega32u4)
|
||||
BOOTLOADER_SIZE = 4096
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
BOOTLOADER_SIZE = 8192
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_QMK_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifeq ($(strip $(MCU)), atmega32u4)
|
||||
BOOTLOADER_SIZE = 4096
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
BOOTLOADER_SIZE = 8192
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), halfkay)
|
||||
OPT_DEFS += -DBOOTLOADER_HALFKAY
|
||||
ifeq ($(strip $(MCU)), atmega32u4)
|
||||
BOOTLOADER_SIZE = 512
|
||||
BOOTLOADER_SIZE = 512
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
BOOTLOADER_SIZE = 1024
|
||||
BOOTLOADER_SIZE = 1024
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), caterina)
|
||||
|
||||
@@ -23,5 +23,5 @@ endif
|
||||
|
||||
# Generate the keymap.c
|
||||
ifneq ("$(KEYMAP_JSON)","")
|
||||
_ = $(shell test -e $(KEYMAP_C) || bin/qmk-json-keymap $(KEYMAP_JSON) -o $(KEYMAP_C))
|
||||
_ = $(shell test -e $(KEYMAP_C) || bin/qmk json-keymap $(KEYMAP_JSON) -o $(KEYMAP_C))
|
||||
endif
|
||||
|
||||
@@ -112,7 +112,7 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
|
||||
OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
|
||||
else
|
||||
SRC += ws2812.c
|
||||
WS2812_DRIVER_REQUIRED = yes
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -176,7 +176,7 @@ endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), WS2812)
|
||||
OPT_DEFS += -DWS2812
|
||||
SRC += ws2812.c
|
||||
WS2812_DRIVER_REQUIRED = yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
|
||||
@@ -233,11 +233,37 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
|
||||
ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
|
||||
CIE1931_CURVE = yes
|
||||
endif
|
||||
ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
|
||||
|
||||
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/backlight
|
||||
SRC += $(QUANTUM_DIR)/backlight/backlight.c
|
||||
OPT_DEFS += -DBACKLIGHT_ENABLE
|
||||
|
||||
ifeq ($(strip $(BACKLIGHT_ENABLE)), custom)
|
||||
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
||||
endif
|
||||
endif
|
||||
|
||||
VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c
|
||||
|
||||
WS2812_DRIVER ?= bitbang
|
||||
ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
|
||||
ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),)
|
||||
$(error WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(WS2812_DRIVER)), bitbang)
|
||||
SRC += ws2812.c
|
||||
else
|
||||
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
|
||||
endif
|
||||
|
||||
# add extra deps
|
||||
ifeq ($(strip $(WS2812_DRIVER)), i2c)
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CIE1931_CURVE)), yes)
|
||||
OPT_DEFS += -DUSE_CIE1931_CURVE
|
||||
LED_TABLES = yes
|
||||
@@ -262,6 +288,10 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes)
|
||||
include $(TMK_DIR)/protocol/usb_hid.mk
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(WEBUSB_ENABLE)), yes)
|
||||
SRC += $(TMK_DIR)/common/webusb.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ENCODER_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/encoder.c
|
||||
OPT_DEFS += -DENCODER_ENABLE
|
||||
@@ -358,3 +388,9 @@ ifeq ($(strip $(SPACE_CADET_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
|
||||
OPT_DEFS += -DSPACE_CADET_ENABLE
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/dip_switch.c
|
||||
OPT_DEFS += -DDIP_SWITCH_ENABLE
|
||||
endif
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
* LUFA USB descriptor cleanup
|
||||
* Some code cleanups related to the USB HID descriptors on AVR keyboards, to make them easier to read and understand
|
||||
* More information: see https://github.com/qmk/qmk_firmware/pull/4871
|
||||
* No behaviour changes anticipated and no keymaps modified
|
||||
@@ -1,5 +0,0 @@
|
||||
* Update repo to use LUFA as a git submodule
|
||||
* `/lib/LUFA` removed from the repo
|
||||
* LUFA set as a submodule, pointing to qmk/lufa
|
||||
* This should allow more flexibility with LUFA, and allow us to keep the sub-module up to date, a lot more easily. It was ~2 years out of date with no easy path to fix that. This prevents that from being an issue in the future
|
||||
|
||||
1
drivers/arm/ws2812.c
Normal file
1
drivers/arm/ws2812.c
Normal file
@@ -0,0 +1 @@
|
||||
#error("NOT SUPPORTED")
|
||||
1
drivers/arm/ws2812_pwm.c
Normal file
1
drivers/arm/ws2812_pwm.c
Normal file
@@ -0,0 +1 @@
|
||||
#error("NOT SUPPORTED")
|
||||
1
drivers/arm/ws2812_spi.c
Normal file
1
drivers/arm/ws2812_spi.c
Normal file
@@ -0,0 +1 @@
|
||||
#error("NOT SUPPORTED")
|
||||
@@ -19,9 +19,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void analogReference(uint8_t mode);
|
||||
int16_t analogRead(uint8_t pin);
|
||||
int16_t adc_read(uint8_t mux);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ADC_REF_POWER (1 << REFS0)
|
||||
#define ADC_REF_INTERNAL ((1 << REFS1) | (1 << REFS0))
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
#ifndef F_SCL
|
||||
# define F_SCL 400000UL // SCL frequency
|
||||
#endif
|
||||
#define Prescaler 1
|
||||
#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16) / 2)
|
||||
|
||||
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
|
||||
|
||||
void i2c_init(void) {
|
||||
TWSR = 0; /* no prescaler */
|
||||
|
||||
@@ -25,13 +25,17 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(LED_ARRAY) && defined(RGB_MATRIX_ENABLE)
|
||||
// LED color buffer
|
||||
LED_TYPE led[DRIVER_LED_TOTAL];
|
||||
# define LED_ARRAY led
|
||||
#endif
|
||||
/*
|
||||
* Forward declare internal functions
|
||||
*
|
||||
* The functions take a byte-array and send to the data output as WS2812 bitstream.
|
||||
* The length is the number of bytes to send - three per LED.
|
||||
*/
|
||||
|
||||
void ws2812_sendarray(uint8_t *array, uint16_t length);
|
||||
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
|
||||
|
||||
|
||||
#ifdef RGBW_BB_TWI
|
||||
|
||||
@@ -135,23 +139,6 @@ unsigned char I2C_Write(unsigned char c) {
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
// Set an led in the buffer to a color
|
||||
void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
led[i].r = r;
|
||||
led[i].g = g;
|
||||
led[i].b = b;
|
||||
}
|
||||
|
||||
void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b) {
|
||||
for (int i = 0; i < sizeof(led) / sizeof(led[0]); i++) {
|
||||
led[i].r = r;
|
||||
led[i].g = g;
|
||||
led[i].b = b;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setleds for standard RGB
|
||||
void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
|
||||
// ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
|
||||
|
||||
@@ -20,13 +20,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIGHT_WS2812_H_
|
||||
#define LIGHT_WS2812_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
//#include "ws2812_config.h"
|
||||
//#include "i2cmaster.h"
|
||||
#pragma once
|
||||
|
||||
#include "quantum/color.h"
|
||||
|
||||
@@ -42,33 +36,6 @@
|
||||
* - Send out the LED data
|
||||
* - Wait 50<35>s to reset the LEDs
|
||||
*/
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
void ws2812_setled(int index, uint8_t r, uint8_t g, uint8_t b);
|
||||
void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b);
|
||||
#endif
|
||||
|
||||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
|
||||
void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask);
|
||||
void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
|
||||
|
||||
/*
|
||||
* Old interface / Internal functions
|
||||
*
|
||||
* The functions take a byte-array and send to the data output as WS2812 bitstream.
|
||||
* The length is the number of bytes to send - three per LED.
|
||||
*/
|
||||
|
||||
void ws2812_sendarray(uint8_t *array, uint16_t length);
|
||||
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
|
||||
|
||||
/*
|
||||
* Internal defines
|
||||
*/
|
||||
#ifndef CONCAT
|
||||
# define CONCAT(a, b) a##b
|
||||
#endif
|
||||
#ifndef CONCAT_EXP
|
||||
# define CONCAT_EXP(a, b) CONCAT(a, b)
|
||||
#endif
|
||||
|
||||
#endif /* LIGHT_WS2812_H_ */
|
||||
|
||||
31
drivers/avr/ws2812_i2c.c
Normal file
31
drivers/avr/ws2812_i2c.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "ws2812.h"
|
||||
#include "i2c_master.h"
|
||||
|
||||
#ifndef WS2812_ADDRESS
|
||||
# define WS2812_ADDRESS 0xb0
|
||||
#endif
|
||||
|
||||
#ifndef WS2812_TIMEOUT
|
||||
# define WS2812_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
void ws2812_init(void) { i2c_init(); }
|
||||
|
||||
// Setleds for standard RGB
|
||||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
|
||||
static bool s_init = false;
|
||||
if (!s_init) {
|
||||
ws2812_init();
|
||||
s_init = true;
|
||||
}
|
||||
|
||||
i2c_transmit(WS2812_ADDRESS, (uint8_t *)ledarray, sizeof(LED_TYPE) * leds, WS2812_TIMEOUT);
|
||||
}
|
||||
|
||||
// Setleds for SK6812RGBW
|
||||
void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) {
|
||||
// not supported - for now error out if its enabled
|
||||
#ifdef RGBW
|
||||
# error "RGBW not supported"
|
||||
#endif
|
||||
}
|
||||
@@ -114,6 +114,17 @@ void DRV_init(void) {
|
||||
DRV_write(DRV_GO, 0x01);
|
||||
}
|
||||
|
||||
void DRV_rtp_init(void) {
|
||||
DRV_write(DRV_GO, 0x00);
|
||||
DRV_write(DRV_RTP_INPUT, 20); //20 is the lowest value I've found where haptics can still be felt.
|
||||
DRV_write(DRV_MODE, 0x05);
|
||||
DRV_write(DRV_GO, 0x01);
|
||||
}
|
||||
|
||||
void DRV_amplitude(uint8_t amplitude) {
|
||||
DRV_write(DRV_RTP_INPUT, amplitude);
|
||||
}
|
||||
|
||||
void DRV_pulse(uint8_t sequence) {
|
||||
DRV_write(DRV_GO, 0x00);
|
||||
DRV_write(DRV_WAVEFORM_SEQ_1, sequence);
|
||||
|
||||
@@ -170,6 +170,8 @@
|
||||
void DRV_init(void);
|
||||
void DRV_write(const uint8_t drv_register, const uint8_t settings);
|
||||
uint8_t DRV_read(const uint8_t regaddress);
|
||||
void DRV_rtp_init(void);
|
||||
void DRV_amplitude(const uint8_t amplitude);
|
||||
void DRV_pulse(const uint8_t sequence);
|
||||
|
||||
typedef enum DRV_EFFECT {
|
||||
|
||||
@@ -168,6 +168,15 @@ void haptic_set_mode(uint8_t mode) {
|
||||
xprintf("haptic_config.mode = %u\n", haptic_config.mode);
|
||||
}
|
||||
|
||||
void haptic_set_amplitude(uint8_t amp) {
|
||||
haptic_config.amplitude = amp;
|
||||
eeconfig_update_haptic(haptic_config.raw);
|
||||
xprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude);
|
||||
#ifdef DRV2605L
|
||||
DRV_amplitude(amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void haptic_set_buzz(uint8_t buzz) {
|
||||
haptic_config.buzz = buzz;
|
||||
eeconfig_update_haptic(haptic_config.raw);
|
||||
@@ -201,6 +210,53 @@ uint8_t haptic_get_dwell(void) {
|
||||
return haptic_config.dwell;
|
||||
}
|
||||
|
||||
void haptic_enable_continuous(void) {
|
||||
haptic_config.cont = 1;
|
||||
xprintf("haptic_config.cont = %u\n", haptic_config.cont);
|
||||
eeconfig_update_haptic(haptic_config.raw);
|
||||
#ifdef DRV2605L
|
||||
DRV_rtp_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void haptic_disable_continuous(void) {
|
||||
haptic_config.cont = 0;
|
||||
xprintf("haptic_config.cont = %u\n", haptic_config.cont);
|
||||
eeconfig_update_haptic(haptic_config.raw);
|
||||
#ifdef DRV2605L
|
||||
DRV_write(DRV_MODE,0x00);
|
||||
#endif
|
||||
}
|
||||
|
||||
void haptic_toggle_continuous(void) {
|
||||
#ifdef DRV2605L
|
||||
if (haptic_config.cont) {
|
||||
haptic_disable_continuous();
|
||||
} else {
|
||||
haptic_enable_continuous();
|
||||
}
|
||||
eeconfig_update_haptic(haptic_config.raw);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void haptic_cont_increase(void) {
|
||||
uint8_t amp = haptic_config.amplitude + 10;
|
||||
if (haptic_config.amplitude >= 120) {
|
||||
amp = 120;
|
||||
}
|
||||
haptic_set_amplitude(amp);
|
||||
}
|
||||
|
||||
void haptic_cont_decrease(void) {
|
||||
uint8_t amp = haptic_config.amplitude - 10;
|
||||
if (haptic_config.amplitude < 20) {
|
||||
amp = 20;
|
||||
}
|
||||
haptic_set_amplitude(amp);
|
||||
}
|
||||
|
||||
|
||||
void haptic_play(void) {
|
||||
#ifdef DRV2605L
|
||||
uint8_t play_eff = 0;
|
||||
@@ -213,6 +269,7 @@ void haptic_play(void) {
|
||||
}
|
||||
|
||||
bool process_haptic(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
if (keycode == HPT_ON && record->event.pressed) {
|
||||
haptic_enable();
|
||||
}
|
||||
@@ -243,6 +300,16 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == HPT_DWLD && record->event.pressed) {
|
||||
haptic_dwell_decrease();
|
||||
}
|
||||
if (keycode == HPT_CONT && record->event.pressed) {
|
||||
haptic_toggle_continuous();
|
||||
}
|
||||
if (keycode == HPT_CONI && record->event.pressed) {
|
||||
haptic_cont_increase();
|
||||
}
|
||||
if (keycode == HPT_COND && record->event.pressed) {
|
||||
haptic_cont_decrease();
|
||||
}
|
||||
|
||||
if (haptic_config.enable) {
|
||||
if (record->event.pressed) {
|
||||
// keypress
|
||||
|
||||
@@ -34,12 +34,14 @@
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
bool enable : 1;
|
||||
uint8_t feedback : 2;
|
||||
uint8_t mode : 7;
|
||||
bool buzz : 1;
|
||||
uint8_t dwell : 7;
|
||||
uint16_t reserved : 16;
|
||||
bool enable :1;
|
||||
uint8_t feedback :2;
|
||||
uint8_t mode :7;
|
||||
bool buzz :1;
|
||||
uint8_t dwell :7;
|
||||
bool cont :1;
|
||||
uint8_t amplitude :8;
|
||||
uint16_t reserved :7;
|
||||
};
|
||||
} haptic_config_t;
|
||||
|
||||
@@ -71,6 +73,9 @@ uint8_t haptic_get_mode(void);
|
||||
uint8_t haptic_get_feedback(void);
|
||||
void haptic_dwell_increase(void);
|
||||
void haptic_dwell_decrease(void);
|
||||
void haptic_toggle_continuous(void);
|
||||
void haptic_cont_increase(void);
|
||||
void haptic_cont_decrease(void);
|
||||
|
||||
void haptic_play(void);
|
||||
void haptic_shutdown(void);
|
||||
|
||||
@@ -83,7 +83,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define CHARGE_PUMP 0x8D
|
||||
|
||||
// Misc defines
|
||||
#define OLED_TIMEOUT 60000
|
||||
#define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
|
||||
#define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x1307
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER ErgoDox EZ
|
||||
#define PRODUCT ErgoDox EZ
|
||||
#define MANUFACTURER ZSA
|
||||
#define PRODUCT Ergodox EZ
|
||||
#define DESCRIPTION QMK keyboard firmware for Ergodox EZ
|
||||
#define WEBUSB_LANDING_PAGE_URL u8"configure.ergodox-ez.com"
|
||||
|
||||
/* key matrix size */
|
||||
#define MATRIX_ROWS 14
|
||||
@@ -101,7 +102,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* manufacturer specs.
|
||||
*/
|
||||
|
||||
#define DEBOUNCE 15
|
||||
#define DEBOUNCE 30
|
||||
|
||||
#define USB_MAX_POWER_CONSUMPTION 500
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
#ifdef WEBUSB_ENABLE
|
||||
#include "webusb.h"
|
||||
#endif
|
||||
|
||||
extern inline void ergodox_board_led_on(void);
|
||||
extern inline void ergodox_right_led_1_on(void);
|
||||
extern inline void ergodox_right_led_2_on(void);
|
||||
@@ -336,6 +340,17 @@ void keyboard_post_init_kb(void) {
|
||||
|
||||
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifdef WEBUSB_ENABLE
|
||||
if(webusb_state.paired == true) {
|
||||
uint8_t event[5];
|
||||
event[0] = WEBUSB_STATUS_OK;
|
||||
event[1] = record->event.pressed ? WEBUSB_EVT_KEYDOWN : WEBUSB_EVT_KEYUP;
|
||||
event[2] = record->event.key.col;
|
||||
event[3] = record->event.key.row;
|
||||
event[4] = WEBUSB_STOP_BIT;
|
||||
webusb_send(event, sizeof(event));
|
||||
}
|
||||
#endif
|
||||
switch (keycode) {
|
||||
case LED_LEVEL:
|
||||
if (record->event.pressed) {
|
||||
@@ -387,3 +402,53 @@ void eeconfig_init_kb(void) { // EEPROM is getting reset!
|
||||
eeconfig_update_kb(keyboard_config.raw);
|
||||
eeconfig_init_user();
|
||||
}
|
||||
|
||||
#ifdef WEBUSB_ENABLE
|
||||
static uint16_t loops = 0;
|
||||
static bool is_on = false;
|
||||
|
||||
void matrix_scan_kb(void) {
|
||||
if(webusb_state.pairing == true) {
|
||||
if(loops == 0) {
|
||||
ergodox_right_led_1_off();
|
||||
ergodox_right_led_2_off();
|
||||
ergodox_right_led_3_off();
|
||||
}
|
||||
if(loops % WEBUSB_BLINK_STEPS == 0) {
|
||||
if(is_on) {
|
||||
ergodox_right_led_2_off();
|
||||
}
|
||||
else {
|
||||
ergodox_right_led_2_on();
|
||||
}
|
||||
is_on ^= 1;
|
||||
}
|
||||
if(loops > WEBUSB_BLINK_END) {
|
||||
webusb_state.pairing = false;
|
||||
layer_state_set_user(layer_state);
|
||||
loops = 0;
|
||||
}
|
||||
loops++;
|
||||
}
|
||||
else if(loops > 0) {
|
||||
loops = 0;
|
||||
layer_state_set_user(layer_state);
|
||||
}
|
||||
matrix_scan_user();
|
||||
}
|
||||
|
||||
uint32_t layer_state_set_kb(uint32_t state) {
|
||||
state = layer_state_set_user(state);
|
||||
uint8_t layer = biton32(state);
|
||||
if(webusb_state.paired == true) {
|
||||
uint8_t event[4];
|
||||
event[0] = WEBUSB_STATUS_OK;
|
||||
event[1] = WEBUSB_EVT_LAYER;
|
||||
event[2] = layer;
|
||||
event[3] = WEBUSB_STOP_BIT;
|
||||
webusb_send(event, sizeof(event));
|
||||
}
|
||||
return state;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
1
keyboards/ergodox_ez/keymaps/webusb/default.png.md
Normal file
1
keyboards/ergodox_ez/keymaps/webusb/default.png.md
Normal file
@@ -0,0 +1 @@
|
||||
https://i.imgur.com/fKX0Zbs.png
|
||||
@@ -0,0 +1 @@
|
||||
https://i.imgur.com/giAc3M9.jpg
|
||||
147
keyboards/ergodox_ez/keymaps/webusb/keymap.c
Normal file
147
keyboards/ergodox_ez/keymaps/webusb/keymap.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
#include "version.h"
|
||||
#include "keymap_german.h"
|
||||
#include "keymap_nordic.h"
|
||||
#include "keymap_french.h"
|
||||
#include "keymap_spanish.h"
|
||||
#include "keymap_hungarian.h"
|
||||
#include "keymap_swedish.h"
|
||||
#include "keymap_br_abnt2.h"
|
||||
#include "keymap_canadian_multilingual.h"
|
||||
#include "keymap_german_ch.h"
|
||||
#include "keymap_jp.h"
|
||||
|
||||
#define KC_MAC_UNDO LGUI(KC_Z)
|
||||
#define KC_MAC_CUT LGUI(KC_X)
|
||||
#define KC_MAC_COPY LGUI(KC_C)
|
||||
#define KC_MAC_PASTE LGUI(KC_V)
|
||||
#define KC_PC_UNDO LCTL(KC_Z)
|
||||
#define KC_PC_CUT LCTL(KC_X)
|
||||
#define KC_PC_COPY LCTL(KC_C)
|
||||
#define KC_PC_PASTE LCTL(KC_V)
|
||||
#define ES_LESS_MAC KC_GRAVE
|
||||
#define ES_GRTR_MAC LSFT(KC_GRAVE)
|
||||
#define ES_BSLS_MAC ALGR(KC_6)
|
||||
|
||||
enum custom_keycodes {
|
||||
RGB_SLD = EZ_SAFE_RANGE,
|
||||
HSV_172_255_255,
|
||||
HSV_86_255_128,
|
||||
HSV_27_255_255,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = LAYOUT_ergodox_pretty(
|
||||
WEBUSB_PAIR, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT, KC_RIGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS,
|
||||
KC_DELETE, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1), TG(1), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLASH,
|
||||
KC_BSPACE, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, LT(2,KC_SCOLON),LGUI_T(KC_QUOTE),
|
||||
KC_LSHIFT, LCTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_HYPR, KC_MEH, KC_N, KC_M, KC_COMMA, KC_DOT, RCTL_T(KC_SLASH),KC_RSHIFT,
|
||||
LT(1,KC_GRAVE), KC_QUOTE, LALT(KC_LSHIFT),KC_LEFT, KC_RIGHT, KC_UP, KC_DOWN, KC_LBRACKET, KC_RBRACKET, MO(1),
|
||||
LALT_T(KC_APPLICATION),KC_LGUI, KC_LALT, LCTL_T(KC_ESCAPE),
|
||||
KC_HOME, KC_PGUP,
|
||||
KC_SPACE, KC_BSPACE, KC_END, KC_PGDOWN, KC_TAB, KC_ENTER
|
||||
),
|
||||
[1] = LAYOUT_ergodox_pretty(
|
||||
KC_ESCAPE, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRANSPARENT, KC_TRANSPARENT, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
|
||||
KC_TRANSPARENT, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_TRANSPARENT, KC_TRANSPARENT, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
|
||||
KC_TRANSPARENT, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRAVE, KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_PERC, KC_CIRC, KC_LBRACKET, KC_RBRACKET, KC_TILD, KC_TRANSPARENT, KC_TRANSPARENT, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLASH, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_DOT, KC_0, KC_EQUAL, KC_TRANSPARENT,
|
||||
RGB_MOD, HSV_172_255_255,RGB_TOG, RGB_SLD,
|
||||
HSV_86_255_128, KC_TRANSPARENT,
|
||||
RGB_VAD, RGB_VAI, HSV_27_255_255, KC_TRANSPARENT, RGB_HUD, RGB_HUI
|
||||
),
|
||||
[2] = LAYOUT_ergodox_pretty(
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_MS_UP, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_MEDIA_PLAY_PAUSE,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_MEDIA_PREV_TRACK,KC_MEDIA_NEXT_TRACK,KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_MS_BTN1, KC_MS_BTN2, KC_AUDIO_VOL_UP,KC_AUDIO_VOL_DOWN,KC_AUDIO_MUTE, KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT,
|
||||
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_WWW_BACK
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
bool suspended = false;
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case RGB_SLD:
|
||||
if (record->event.pressed) {
|
||||
rgblight_mode(1);
|
||||
}
|
||||
return false;
|
||||
case HSV_172_255_255:
|
||||
if (record->event.pressed) {
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
rgblight_enable();
|
||||
rgblight_mode(1);
|
||||
rgblight_sethsv(172,255,255);
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
case HSV_86_255_128:
|
||||
if (record->event.pressed) {
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
rgblight_enable();
|
||||
rgblight_mode(1);
|
||||
rgblight_sethsv(86,255,128);
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
case HSV_27_255_255:
|
||||
if (record->event.pressed) {
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
rgblight_enable();
|
||||
rgblight_mode(1);
|
||||
rgblight_sethsv(27,255,255);
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t layer_state_set_user(uint32_t state) {
|
||||
|
||||
uint8_t layer = biton32(state);
|
||||
|
||||
ergodox_board_led_off();
|
||||
ergodox_right_led_1_off();
|
||||
ergodox_right_led_2_off();
|
||||
ergodox_right_led_3_off();
|
||||
switch (layer) {
|
||||
case 1:
|
||||
ergodox_right_led_1_on();
|
||||
break;
|
||||
case 2:
|
||||
ergodox_right_led_2_on();
|
||||
break;
|
||||
case 3:
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
case 4:
|
||||
ergodox_right_led_1_on();
|
||||
ergodox_right_led_2_on();
|
||||
break;
|
||||
case 5:
|
||||
ergodox_right_led_1_on();
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
case 6:
|
||||
ergodox_right_led_2_on();
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
case 7:
|
||||
ergodox_right_led_1_on();
|
||||
ergodox_right_led_2_on();
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
|
||||
};
|
||||
15
keyboards/ergodox_ez/keymaps/webusb/readme.md
Normal file
15
keyboards/ergodox_ez/keymaps/webusb/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# ErgoDox EZ Default Configuration
|
||||
|
||||
## Changelog
|
||||
|
||||
* Dec 2016:
|
||||
* Added LED keys
|
||||
* Refreshed layout graphic, comes from http://configure.ergodox-ez.com now.
|
||||
* Sep 22, 2016:
|
||||
* Created a new key in layer 1 (bottom-corner key) that resets the EEPROM.
|
||||
* Feb 2, 2016 (V1.1):
|
||||
* Made the right-hand quote key double as Cmd/Win on hold. So you get ' when you tap it, " when you tap it with Shift, and Cmd or Win when you hold it. You can then use it as a modifier, or just press and hold it for a moment (and then let go) to send a single Cmd or Win keystroke (handy for opening the Start menu on Windows).
|
||||
|
||||
This is what we ship with out of the factory. :) The image says it all:
|
||||
|
||||

|
||||
1
keyboards/ergodox_ez/keymaps/webusb/rules.mk
Normal file
1
keyboards/ergodox_ez/keymaps/webusb/rules.mk
Normal file
@@ -0,0 +1 @@
|
||||
WEBUSB_ENABLE = yes
|
||||
@@ -35,9 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "matrix.h"
|
||||
#include "debounce.h"
|
||||
#include QMK_KEYBOARD_H
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
# include "timer.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This constant define not debouncing time in msecs, assuming eager_pr.
|
||||
@@ -67,11 +64,6 @@ static void select_row(uint8_t row);
|
||||
static uint8_t mcp23018_reset_loop;
|
||||
// static uint16_t mcp23018_reset_loop;
|
||||
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
uint32_t matrix_timer;
|
||||
uint32_t matrix_scan_count;
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) void matrix_init_user(void) {}
|
||||
|
||||
__attribute__((weak)) void matrix_scan_user(void) {}
|
||||
@@ -95,13 +87,9 @@ void matrix_init(void) {
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
raw_matrix[i] = 0;
|
||||
raw_matrix[i] = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
matrix_timer = timer_read32();
|
||||
matrix_scan_count = 0;
|
||||
#endif
|
||||
debounce_init(MATRIX_ROWS);
|
||||
matrix_init_quantum();
|
||||
}
|
||||
@@ -116,11 +104,6 @@ void matrix_power_up(void) {
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
matrix_timer = timer_read32();
|
||||
matrix_scan_count = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Reads and stores a row, returning
|
||||
@@ -151,24 +134,10 @@ uint8_t matrix_scan(void) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
matrix_scan_count++;
|
||||
|
||||
uint32_t timer_now = timer_read32();
|
||||
if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
|
||||
print("matrix scan frequency: ");
|
||||
pdec(matrix_scan_count);
|
||||
print("\n");
|
||||
|
||||
matrix_timer = timer_now;
|
||||
matrix_scan_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LEFT_LEDS
|
||||
mcp23018_status = ergodox_left_leds_update();
|
||||
#endif // LEFT_LEDS
|
||||
bool changed = false;
|
||||
bool changed = false;
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
|
||||
// select rows from left and right hands
|
||||
uint8_t left_index = i;
|
||||
@@ -178,13 +147,13 @@ uint8_t matrix_scan(void) {
|
||||
|
||||
// we don't need a 30us delay anymore, because selecting a
|
||||
// left-hand row requires more than 30us for i2c.
|
||||
|
||||
|
||||
changed |= store_raw_matrix_row(left_index);
|
||||
changed |= store_raw_matrix_row(right_index);
|
||||
|
||||
unselect_rows();
|
||||
}
|
||||
|
||||
|
||||
debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
|
||||
matrix_scan_quantum();
|
||||
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
#pragma once
|
||||
|
||||
/* USB Device descriptor parameter */
|
||||
#undef MANUFACTURER
|
||||
#define MANUFACTURER ZSA
|
||||
#undef PRODUCT
|
||||
#define PRODUCT Planck EZ
|
||||
#define DEVICE_VER 0x0000
|
||||
#define WEBUSB_LANDING_PAGE_URL u8"configure.ergodox-ez.com"
|
||||
|
||||
#undef MATRIX_ROWS
|
||||
#undef MATRIX_COLS
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "ez.h"
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#ifdef WEBUSB_ENABLE
|
||||
#include "webusb.h"
|
||||
#endif
|
||||
|
||||
keyboard_config_t keyboard_config;
|
||||
|
||||
@@ -247,6 +250,16 @@ uint32_t layer_state_set_kb(uint32_t state) {
|
||||
planck_ez_right_led_off();
|
||||
state = layer_state_set_user(state);
|
||||
uint8_t layer = biton32(state);
|
||||
#ifdef WEBUSB_ENABLE
|
||||
if(webusb_state.paired == true) {
|
||||
uint8_t event[4];
|
||||
event[0] = WEBUSB_STATUS_OK;
|
||||
event[1] = WEBUSB_EVT_LAYER;
|
||||
event[2] = layer;
|
||||
event[3] = WEBUSB_STOP_BIT;
|
||||
webusb_send(event, sizeof(event));
|
||||
}
|
||||
#endif
|
||||
switch (layer) {
|
||||
case 1:
|
||||
planck_ez_left_led_on();
|
||||
@@ -265,6 +278,17 @@ uint32_t layer_state_set_kb(uint32_t state) {
|
||||
}
|
||||
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifdef WEBUSB_ENABLE
|
||||
if(webusb_state.paired == true) {
|
||||
uint8_t event[5];
|
||||
event[0] = WEBUSB_STATUS_OK;
|
||||
event[1] = record->event.pressed ? WEBUSB_EVT_KEYDOWN : WEBUSB_EVT_KEYUP;
|
||||
event[2] = record->event.key.col;
|
||||
event[3] = record->event.key.row;
|
||||
event[4] = WEBUSB_STOP_BIT;
|
||||
webusb_send(event, sizeof(event));
|
||||
}
|
||||
#endif
|
||||
switch (keycode) {
|
||||
case LED_LEVEL:
|
||||
if (record->event.pressed) {
|
||||
@@ -325,3 +349,38 @@ bool music_mask_kb(uint16_t keycode) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef WEBUSB_ENABLE
|
||||
static uint16_t loops = 0;
|
||||
static bool is_on = false;
|
||||
|
||||
void matrix_scan_kb(void) {
|
||||
if(webusb_state.pairing == true) {
|
||||
if(loops == 0) {
|
||||
//lights off
|
||||
}
|
||||
if(loops % WEBUSB_BLINK_STEPS == 0) {
|
||||
if(is_on) {
|
||||
planck_ez_left_led_on();
|
||||
planck_ez_right_led_off();
|
||||
}
|
||||
else {
|
||||
planck_ez_left_led_off();
|
||||
planck_ez_right_led_on();
|
||||
}
|
||||
is_on ^= 1;
|
||||
}
|
||||
if(loops > WEBUSB_BLINK_END * 2) {
|
||||
webusb_state.pairing = false;
|
||||
loops = 0;
|
||||
planck_ez_left_led_off();
|
||||
planck_ez_right_led_off();
|
||||
}
|
||||
loops++;
|
||||
}
|
||||
else if(loops > 0) {
|
||||
loops = 0;
|
||||
planck_ez_left_led_off();
|
||||
planck_ez_right_led_off();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -292,7 +292,7 @@ void encoder_update(bool clockwise) {
|
||||
}
|
||||
}
|
||||
|
||||
void dip_update(uint8_t index, bool active) {
|
||||
void dip_switch_update_user(uint8_t index, bool active) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
if (active) {
|
||||
|
||||
39
keyboards/planck/keymaps/webusb/config.h
Normal file
39
keyboards/planck/keymaps/webusb/config.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
#define STARTUP_SONG SONG(PLANCK_SOUND)
|
||||
// #define STARTUP_SONG SONG(NO_SOUND)
|
||||
|
||||
#define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
|
||||
SONG(COLEMAK_SOUND), \
|
||||
SONG(DVORAK_SOUND) \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MIDI options
|
||||
*/
|
||||
|
||||
/* Prevent use of disabled MIDI features in the keymap */
|
||||
//#define MIDI_ENABLE_STRICT 1
|
||||
|
||||
/* enable basic MIDI features:
|
||||
- MIDI notes can be sent when in Music mode is on
|
||||
*/
|
||||
|
||||
#define MIDI_BASIC
|
||||
|
||||
/* enable advanced MIDI features:
|
||||
- MIDI notes can be added to the keymap
|
||||
- Octave shift and transpose
|
||||
- Virtual sustain, portamento, and modulation wheel
|
||||
- etc.
|
||||
*/
|
||||
//#define MIDI_ADVANCED
|
||||
|
||||
/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
|
||||
//#define MIDI_TONE_KEYCODE_OCTAVES 2
|
||||
|
||||
// Most tactile encoders have detents every 4 stages
|
||||
#define ENCODER_RESOLUTION 4
|
||||
|
||||
136
keyboards/planck/keymaps/webusb/keymap.c
Normal file
136
keyboards/planck/keymaps/webusb/keymap.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
#ifdef AUDIO_ENABLE
|
||||
#include "muse.h"
|
||||
#endif
|
||||
#include "eeprom.h"
|
||||
#include "keymap_german.h"
|
||||
#include "keymap_nordic.h"
|
||||
#include "keymap_french.h"
|
||||
#include "keymap_spanish.h"
|
||||
#include "keymap_hungarian.h"
|
||||
#include "keymap_swedish.h"
|
||||
#include "keymap_br_abnt2.h"
|
||||
#include "keymap_canadian_multilingual.h"
|
||||
#include "keymap_german_ch.h"
|
||||
#include "keymap_jp.h"
|
||||
|
||||
#define KC_MAC_UNDO LGUI(KC_Z)
|
||||
#define KC_MAC_CUT LGUI(KC_X)
|
||||
#define KC_MAC_COPY LGUI(KC_C)
|
||||
#define KC_MAC_PASTE LGUI(KC_V)
|
||||
#define KC_PC_UNDO LCTL(KC_Z)
|
||||
#define KC_PC_CUT LCTL(KC_X)
|
||||
#define KC_PC_COPY LCTL(KC_C)
|
||||
#define KC_PC_PASTE LCTL(KC_V)
|
||||
#define ES_LESS_MAC KC_GRAVE
|
||||
#define ES_GRTR_MAC LSFT(KC_GRAVE)
|
||||
#define ES_BSLS_MAC ALGR(KC_6)
|
||||
|
||||
enum planck_keycodes {
|
||||
RGB_SLD = EZ_SAFE_RANGE,
|
||||
};
|
||||
|
||||
enum planck_layers {
|
||||
_BASE,
|
||||
_LOWER,
|
||||
_RAISE,
|
||||
_ADJUST,
|
||||
};
|
||||
|
||||
|
||||
#define LOWER MO(_LOWER)
|
||||
#define RAISE MO(_RAISE)
|
||||
|
||||
#define LOWER MO(_LOWER)
|
||||
#define RAISE MO(_RAISE)
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[_BASE] = LAYOUT_planck_grid(KC_TAB,KC_Q,KC_W,KC_E,KC_R,KC_T,KC_Y,KC_U,KC_I,KC_O,KC_P,KC_BSPACE,KC_ESCAPE,KC_A,KC_S,KC_D,KC_F,KC_G,KC_H,KC_J,KC_K,KC_L,KC_SCOLON,KC_QUOTE,KC_LSHIFT,KC_Z,KC_X,KC_C,KC_V,KC_B,KC_N,KC_M,KC_COMMA,KC_DOT,KC_SLASH,KC_ENTER,KC_HYPR,KC_LCTRL,KC_LALT,KC_LGUI,LOWER,KC_SPACE,KC_NO,RAISE,KC_LEFT,KC_DOWN,KC_UP,KC_RIGHT),
|
||||
|
||||
[_LOWER] = LAYOUT_planck_grid(KC_TILD,KC_EXLM,KC_AT,KC_HASH,KC_DLR,KC_PERC,KC_CIRC,KC_AMPR,KC_ASTR,KC_LPRN,KC_RPRN,KC_TRANSPARENT,KC_DELETE,KC_F1,KC_F2,KC_F3,KC_F4,KC_F5,KC_F6,KC_UNDS,KC_PLUS,KC_LCBR,KC_RCBR,KC_PIPE,KC_TRANSPARENT,KC_F7,KC_F8,KC_F9,KC_F10,KC_F11,KC_F12,KC_NONUS_HASH,KC_NONUS_BSLASH,KC_HOME,KC_END,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_NO,KC_TRANSPARENT,KC_MEDIA_NEXT_TRACK,KC_AUDIO_VOL_DOWN,KC_AUDIO_VOL_UP,KC_MEDIA_PLAY_PAUSE),
|
||||
|
||||
[_RAISE] = LAYOUT_planck_grid(KC_GRAVE,KC_1,KC_2,KC_3,KC_4,KC_5,KC_6,KC_7,KC_8,KC_9,KC_0,KC_TRANSPARENT,KC_DELETE,KC_F1,KC_F2,KC_F3,KC_F4,KC_F5,KC_F6,KC_MINUS,KC_EQUAL,KC_LBRACKET,KC_RBRACKET,KC_BSLASH,KC_TRANSPARENT,KC_F7,KC_F8,KC_F9,KC_F10,KC_F11,KC_F12,KC_NONUS_HASH,KC_NONUS_BSLASH,KC_PGUP,KC_PGDOWN,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_NO,KC_TRANSPARENT,KC_MEDIA_NEXT_TRACK,KC_AUDIO_VOL_DOWN,KC_AUDIO_VOL_UP,KC_MEDIA_PLAY_PAUSE),
|
||||
|
||||
[_ADJUST] = LAYOUT_planck_grid(WEBUSB_PAIR,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_DELETE,KC_TRANSPARENT,AU_ON,AU_OFF,AU_TOG,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,RESET,KC_TRANSPARENT,KC_TRANSPARENT,MU_ON,MU_OFF,MU_TOG,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_NO,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT,KC_TRANSPARENT),
|
||||
|
||||
};
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
bool muse_mode = false;
|
||||
uint8_t last_muse_note = 0;
|
||||
uint16_t muse_counter = 0;
|
||||
uint8_t muse_offset = 70;
|
||||
uint16_t muse_tempo = 50;
|
||||
|
||||
void encoder_update(bool clockwise) {
|
||||
if (muse_mode) {
|
||||
if (IS_LAYER_ON(_RAISE)) {
|
||||
if (clockwise) {
|
||||
muse_offset++;
|
||||
} else {
|
||||
muse_offset--;
|
||||
}
|
||||
} else {
|
||||
if (clockwise) {
|
||||
muse_tempo+=1;
|
||||
} else {
|
||||
muse_tempo-=1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (clockwise) {
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
register_code(KC_MS_WH_DOWN);
|
||||
unregister_code(KC_MS_WH_DOWN);
|
||||
#else
|
||||
register_code(KC_PGDN);
|
||||
unregister_code(KC_PGDN);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
register_code(KC_MS_WH_UP);
|
||||
unregister_code(KC_MS_WH_UP);
|
||||
#else
|
||||
register_code(KC_PGUP);
|
||||
unregister_code(KC_PGUP);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void matrix_scan_user(void) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
if (muse_mode) {
|
||||
if (muse_counter == 0) {
|
||||
uint8_t muse_note = muse_offset + SCALE[muse_clock_pulse()];
|
||||
if (muse_note != last_muse_note) {
|
||||
stop_note(compute_freq_for_midi_note(last_muse_note));
|
||||
play_note(compute_freq_for_midi_note(muse_note), 0xF);
|
||||
last_muse_note = muse_note;
|
||||
}
|
||||
}
|
||||
muse_counter = (muse_counter + 1) % muse_tempo;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool music_mask_user(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case RAISE:
|
||||
case LOWER:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t layer_state_set_user(uint32_t state) {
|
||||
return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
|
||||
}
|
||||
2
keyboards/planck/keymaps/webusb/readme.md
Normal file
2
keyboards/planck/keymaps/webusb/readme.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# The Default Planck Layout
|
||||
|
||||
3
keyboards/planck/keymaps/webusb/rules.mk
Normal file
3
keyboards/planck/keymaps/webusb/rules.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
SRC += muse.c
|
||||
RGB_MATRIX_ENABLE = no
|
||||
WEBUSB_ENABLE = yes
|
||||
2
lib/lufa
2
lib/lufa
Submodule lib/lufa updated: ce10f7642b...94e43e4977
@@ -17,6 +17,7 @@ import argparse
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
from decimal import Decimal
|
||||
from tempfile import NamedTemporaryFile
|
||||
@@ -35,6 +36,10 @@ except ImportError:
|
||||
|
||||
import argcomplete
|
||||
import colorama
|
||||
from appdirs import user_config_dir
|
||||
|
||||
# Disable logging until we can configure it how the user wants
|
||||
logging.basicConfig(filename='/dev/null')
|
||||
|
||||
# Log Level Representations
|
||||
EMOJI_LOGLEVELS = {
|
||||
@@ -47,6 +52,7 @@ EMOJI_LOGLEVELS = {
|
||||
}
|
||||
EMOJI_LOGLEVELS['FATAL'] = EMOJI_LOGLEVELS['CRITICAL']
|
||||
EMOJI_LOGLEVELS['WARN'] = EMOJI_LOGLEVELS['WARNING']
|
||||
UNICODE_SUPPORT = sys.stdout.encoding.lower().startswith('utf')
|
||||
|
||||
# ANSI Color setup
|
||||
# Regex was gratefully borrowed from kfir on stackoverflow:
|
||||
@@ -97,11 +103,12 @@ class ANSIFormatter(logging.Formatter):
|
||||
|
||||
|
||||
class ANSIEmojiLoglevelFormatter(ANSIFormatter):
|
||||
"""A log formatter that makes the loglevel an emoji.
|
||||
"""A log formatter that makes the loglevel an emoji on UTF capable terminals.
|
||||
"""
|
||||
|
||||
def format(self, record):
|
||||
record.levelname = EMOJI_LOGLEVELS[record.levelname].format(**ansi_colors)
|
||||
if UNICODE_SUPPORT:
|
||||
record.levelname = EMOJI_LOGLEVELS[record.levelname].format(**ansi_colors)
|
||||
return super(ANSIEmojiLoglevelFormatter, self).format(record)
|
||||
|
||||
|
||||
@@ -144,13 +151,15 @@ class Configuration(object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._config = {}
|
||||
self.default_container = ConfigurationOption
|
||||
|
||||
def __getattr__(self, key):
|
||||
return self.__getitem__(key)
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Returns a config section, creating it if it doesn't exist yet.
|
||||
"""
|
||||
if key not in self._config:
|
||||
self.__dict__[key] = self._config[key] = ConfigurationOption()
|
||||
self.__dict__[key] = self._config[key] = ConfigurationSection(self)
|
||||
|
||||
return self._config[key]
|
||||
|
||||
@@ -161,30 +170,34 @@ class Configuration(object):
|
||||
def __delitem__(self, key):
|
||||
if key in self.__dict__ and key[0] != '_':
|
||||
del self.__dict__[key]
|
||||
del self._config[key]
|
||||
if key in self._config:
|
||||
del self._config[key]
|
||||
|
||||
|
||||
class ConfigurationOption(Configuration):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ConfigurationOption, self).__init__(*args, **kwargs)
|
||||
self.default_container = dict
|
||||
class ConfigurationSection(Configuration):
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
super(ConfigurationSection, self).__init__(*args, **kwargs)
|
||||
self.parent = parent
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Returns a config section, creating it if it doesn't exist yet.
|
||||
"""Returns a config value, pulling from the `user` section as a fallback.
|
||||
"""
|
||||
if key not in self._config:
|
||||
self.__dict__[key] = self._config[key] = None
|
||||
if key in self._config:
|
||||
return self._config[key]
|
||||
|
||||
return self._config[key]
|
||||
elif key in self.parent.user:
|
||||
return self.parent.user[key]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def handle_store_boolean(self, *args, **kwargs):
|
||||
"""Does the add_argument for action='store_boolean'.
|
||||
"""
|
||||
kwargs['add_dest'] = False
|
||||
disabled_args = None
|
||||
disabled_kwargs = kwargs.copy()
|
||||
disabled_kwargs['action'] = 'store_false'
|
||||
disabled_kwargs['dest'] = self.get_argument_name(*args, **kwargs)
|
||||
disabled_kwargs['help'] = 'Disable ' + kwargs['help']
|
||||
kwargs['action'] = 'store_true'
|
||||
kwargs['help'] = 'Enable ' + kwargs['help']
|
||||
@@ -219,11 +232,6 @@ class SubparserWrapper(object):
|
||||
self.subparser.completer = completer
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
if kwargs.get('add_dest', True):
|
||||
kwargs['dest'] = self.submodule + '_' + self.cli.get_argument_name(*args, **kwargs)
|
||||
if 'add_dest' in kwargs:
|
||||
del kwargs['add_dest']
|
||||
|
||||
if 'action' in kwargs and kwargs['action'] == 'store_boolean':
|
||||
return handle_store_boolean(self, *args, **kwargs)
|
||||
|
||||
@@ -254,12 +262,16 @@ class MILC(object):
|
||||
self._entrypoint = None
|
||||
self._inside_context_manager = False
|
||||
self.ansi = ansi_colors
|
||||
self.arg_only = []
|
||||
self.config = Configuration()
|
||||
self.config_file = None
|
||||
self.prog_name = sys.argv[0][:-3] if sys.argv[0].endswith('.py') else sys.argv[0]
|
||||
self.version = os.environ.get('QMK_VERSION', 'unknown')
|
||||
self.release_lock()
|
||||
|
||||
# Figure out our program name
|
||||
self.prog_name = sys.argv[0][:-3] if sys.argv[0].endswith('.py') else sys.argv[0]
|
||||
self.prog_name = self.prog_name.split('/')[-1]
|
||||
|
||||
# Initialize all the things
|
||||
self.initialize_argparse()
|
||||
self.initialize_logging()
|
||||
@@ -273,7 +285,7 @@ class MILC(object):
|
||||
self._description = self._arg_parser.description = self._arg_defaults.description = value
|
||||
|
||||
def echo(self, text, *args, **kwargs):
|
||||
"""Print colorized text to stdout, as long as stdout is a tty.
|
||||
"""Print colorized text to stdout.
|
||||
|
||||
ANSI color strings (such as {fg-blue}) will be converted into ANSI
|
||||
escape sequences, and the ANSI reset sequence will be added to all
|
||||
@@ -284,11 +296,10 @@ class MILC(object):
|
||||
if args and kwargs:
|
||||
raise RuntimeError('You can only specify *args or **kwargs, not both!')
|
||||
|
||||
if sys.stdout.isatty():
|
||||
args = args or kwargs
|
||||
text = format_ansi(text)
|
||||
args = args or kwargs
|
||||
text = format_ansi(text)
|
||||
|
||||
print(text % args)
|
||||
print(text % args)
|
||||
|
||||
def initialize_argparse(self):
|
||||
"""Prepare to process arguments from sys.argv.
|
||||
@@ -313,21 +324,21 @@ class MILC(object):
|
||||
self.release_lock()
|
||||
|
||||
def completer(self, completer):
|
||||
"""Add an arpcomplete completer to this subcommand.
|
||||
"""Add an argcomplete completer to this subcommand.
|
||||
"""
|
||||
self._arg_parser.completer = completer
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
"""Wrapper to add arguments to both the main and the shadow argparser.
|
||||
"""
|
||||
if 'action' in kwargs and kwargs['action'] == 'store_boolean':
|
||||
return handle_store_boolean(self, *args, **kwargs)
|
||||
|
||||
if kwargs.get('add_dest', True) and args[0][0] == '-':
|
||||
kwargs['dest'] = 'general_' + self.get_argument_name(*args, **kwargs)
|
||||
if 'add_dest' in kwargs:
|
||||
del kwargs['add_dest']
|
||||
|
||||
if 'action' in kwargs and kwargs['action'] == 'store_boolean':
|
||||
return handle_store_boolean(self, *args, **kwargs)
|
||||
|
||||
self.acquire_lock()
|
||||
self._arg_parser.add_argument(*args, **kwargs)
|
||||
|
||||
@@ -396,7 +407,7 @@ class MILC(object):
|
||||
if self.args and self.args.general_config_file:
|
||||
return self.args.general_config_file
|
||||
|
||||
return os.path.abspath(os.path.expanduser('~/.%s.ini' % self.prog_name))
|
||||
return os.path.join(user_config_dir(appname='qmk', appauthor='QMK'), '%s.ini' % self.prog_name)
|
||||
|
||||
def get_argument_name(self, *args, **kwargs):
|
||||
"""Takes argparse arguments and returns the dest name.
|
||||
@@ -413,11 +424,17 @@ class MILC(object):
|
||||
raise RuntimeError('You must run this before the with statement!')
|
||||
|
||||
def argument_function(handler):
|
||||
if 'arg_only' in kwargs and kwargs['arg_only']:
|
||||
arg_name = self.get_argument_name(*args, **kwargs)
|
||||
self.arg_only.append(arg_name)
|
||||
del kwargs['arg_only']
|
||||
|
||||
name = handler.__name__.replace("_", "-")
|
||||
if handler is self._entrypoint:
|
||||
self.add_argument(*args, **kwargs)
|
||||
|
||||
elif handler.__name__ in self.subcommands:
|
||||
self.subcommands[handler.__name__].add_argument(*args, **kwargs)
|
||||
elif name in self.subcommands:
|
||||
self.subcommands[name].add_argument(*args, **kwargs)
|
||||
|
||||
else:
|
||||
raise RuntimeError('Decorated function is not entrypoint or subcommand!')
|
||||
@@ -485,15 +502,20 @@ class MILC(object):
|
||||
if argument in ('subparsers', 'entrypoint'):
|
||||
continue
|
||||
|
||||
if '_' not in argument:
|
||||
continue
|
||||
|
||||
section, option = argument.split('_', 1)
|
||||
if hasattr(self.args_passed, argument):
|
||||
self.config[section][option] = getattr(self.args, argument)
|
||||
if '_' in argument:
|
||||
section, option = argument.split('_', 1)
|
||||
else:
|
||||
if option not in self.config[section]:
|
||||
self.config[section][option] = getattr(self.args, argument)
|
||||
section = self._entrypoint.__name__
|
||||
option = argument
|
||||
|
||||
if option not in self.arg_only:
|
||||
if hasattr(self.args_passed, argument):
|
||||
arg_value = getattr(self.args, argument)
|
||||
if arg_value:
|
||||
self.config[section][option] = arg_value
|
||||
else:
|
||||
if option not in self.config[section]:
|
||||
self.config[section][option] = getattr(self.args, argument)
|
||||
|
||||
self.release_lock()
|
||||
|
||||
@@ -509,6 +531,8 @@ class MILC(object):
|
||||
self.acquire_lock()
|
||||
|
||||
config = RawConfigParser()
|
||||
config_dir = os.path.dirname(self.config_file)
|
||||
|
||||
for section_name, section in self.config._config.items():
|
||||
config.add_section(section_name)
|
||||
for option_name, value in section.items():
|
||||
@@ -517,7 +541,10 @@ class MILC(object):
|
||||
continue
|
||||
config.set(section_name, option_name, str(value))
|
||||
|
||||
with NamedTemporaryFile(mode='w', dir=os.path.dirname(self.config_file), delete=False) as tmpfile:
|
||||
if not os.path.exists(config_dir):
|
||||
os.makedirs(config_dir)
|
||||
|
||||
with NamedTemporaryFile(mode='w', dir=config_dir, delete=False) as tmpfile:
|
||||
config.write(tmpfile)
|
||||
|
||||
# Move the new config file into place atomically
|
||||
@@ -527,6 +554,7 @@ class MILC(object):
|
||||
self.log.warning('Config file saving failed, not replacing %s with %s.', self.config_file, tmpfile.name)
|
||||
|
||||
self.release_lock()
|
||||
cli.log.info('Wrote configuration to %s', shlex.quote(self.config_file))
|
||||
|
||||
def __call__(self):
|
||||
"""Execute the entrypoint function.
|
||||
@@ -534,8 +562,7 @@ class MILC(object):
|
||||
if not self._inside_context_manager:
|
||||
# If they didn't use the context manager use it ourselves
|
||||
with self:
|
||||
self.__call__()
|
||||
return
|
||||
return self.__call__()
|
||||
|
||||
if not self._entrypoint:
|
||||
raise RuntimeError('No entrypoint provided!')
|
||||
@@ -573,7 +600,7 @@ class MILC(object):
|
||||
self.add_subparsers()
|
||||
|
||||
if not name:
|
||||
name = handler.__name__
|
||||
name = handler.__name__.replace("_", "-")
|
||||
|
||||
self.acquire_lock()
|
||||
kwargs['help'] = description
|
||||
@@ -603,8 +630,8 @@ class MILC(object):
|
||||
"""Called by __enter__() to setup the logging configuration.
|
||||
"""
|
||||
if len(logging.root.handlers) != 0:
|
||||
# This is not a design decision. This is what I'm doing for now until I can examine and think about this situation in more detail.
|
||||
raise RuntimeError('MILC should be the only system installing root log handlers!')
|
||||
# MILC is the only thing that should have root log handlers
|
||||
logging.root.handlers = []
|
||||
|
||||
self.acquire_lock()
|
||||
|
||||
@@ -649,8 +676,9 @@ class MILC(object):
|
||||
self.read_config()
|
||||
self.setup_logging()
|
||||
|
||||
if self.config.general.save_config:
|
||||
if 'save_config' in self.config.general and self.config.general.save_config:
|
||||
self.save_config()
|
||||
exit(0)
|
||||
|
||||
return self
|
||||
|
||||
@@ -713,4 +741,3 @@ if __name__ == '__main__':
|
||||
cli.goodbye.add_argument('-n', '--name', help='Name to bid farewell to', default='World')
|
||||
|
||||
cli() # Automatically picks between main(), hello() and goodbye()
|
||||
print(sorted(ansi_colors.keys()))
|
||||
|
||||
14
lib/python/qmk/cli/__init__.py
Normal file
14
lib/python/qmk/cli/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""QMK CLI Subcommands
|
||||
|
||||
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
|
||||
"""
|
||||
from . import cformat
|
||||
from . import compile
|
||||
from . import config
|
||||
from . import doctor
|
||||
from . import hello
|
||||
from . import json
|
||||
from . import list
|
||||
from . import new
|
||||
from . import pyformat
|
||||
from . import pytest
|
||||
34
lib/python/qmk/cli/cformat.py
Normal file
34
lib/python/qmk/cli/cformat.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""Format C code according to QMK's style.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.')
|
||||
@cli.subcommand("Format C code according to QMK's style.")
|
||||
def cformat(cli):
|
||||
"""Format C code according to QMK's style.
|
||||
"""
|
||||
clang_format = ['clang-format', '-i']
|
||||
|
||||
# Find the list of files to format
|
||||
if not cli.args.files:
|
||||
for dir in ['drivers', 'quantum', 'tests', 'tmk_core']:
|
||||
for dirpath, dirnames, filenames in os.walk(dir):
|
||||
if 'tmk_core/protocol/usb_hid' in dirpath:
|
||||
continue
|
||||
|
||||
for name in filenames:
|
||||
if name.endswith('.c') or name.endswith('.h') or name.endswith('.cpp'):
|
||||
cli.args.files.append(os.path.join(dirpath, name))
|
||||
|
||||
# Run clang-format on the files we've found
|
||||
try:
|
||||
subprocess.run(clang_format + cli.args.files, check=True)
|
||||
cli.log.info('Successfully formatted the C code.')
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
cli.log.error('Error formatting C code!')
|
||||
return False
|
||||
@@ -14,11 +14,11 @@ import qmk.keymap
|
||||
import qmk.path
|
||||
|
||||
|
||||
@cli.argument('filename', nargs='?', type=FileType('r'), help='The configurator export to compile')
|
||||
@cli.argument('filename', nargs='?', arg_only=True, type=FileType('r'), help='The configurator export to compile')
|
||||
@cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
|
||||
@cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')
|
||||
@cli.entrypoint('Compile a QMK Firmware.')
|
||||
def main(cli):
|
||||
@cli.subcommand('Compile a QMK Firmware.')
|
||||
def compile(cli):
|
||||
"""Compile a QMK Firmware.
|
||||
|
||||
If a Configurator export is supplied this command will create a new keymap, overwriting an existing keymap if one exists.
|
||||
@@ -41,9 +41,9 @@ def main(cli):
|
||||
# Compile the keymap
|
||||
command = ['make', ':'.join((user_keymap['keyboard'], user_keymap['keymap']))]
|
||||
|
||||
elif cli.config.general.keyboard and cli.config.general.keymap:
|
||||
elif cli.config.compile.keyboard and cli.config.compile.keymap:
|
||||
# Generate the make command for a specific keyboard/keymap.
|
||||
command = ['make', ':'.join((cli.config.general.keyboard, cli.config.general.keymap))]
|
||||
command = ['make', ':'.join((cli.config.compile.keyboard, cli.config.compile.keymap))]
|
||||
|
||||
else:
|
||||
cli.log.error('You must supply a configurator export or both `--keyboard` and `--keymap`.')
|
||||
|
||||
96
lib/python/qmk/cli/config.py
Normal file
96
lib/python/qmk/cli/config.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""Read and write configuration settings
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
def print_config(section, key):
|
||||
"""Print a single config setting to stdout.
|
||||
"""
|
||||
cli.echo('%s.%s{fg_cyan}={fg_reset}%s', section, key, cli.config[section][key])
|
||||
|
||||
|
||||
@cli.argument('-ro', '--read-only', action='store_true', help='Operate in read-only mode.')
|
||||
@cli.argument('configs', nargs='*', arg_only=True, help='Configuration options to read or write.')
|
||||
@cli.subcommand("Read and write configuration settings.")
|
||||
def config(cli):
|
||||
"""Read and write config settings.
|
||||
|
||||
This script iterates over the config_tokens supplied as argument. Each config_token has the following form:
|
||||
|
||||
section[.key][=value]
|
||||
|
||||
If only a section (EG 'compile') is supplied all keys for that section will be displayed.
|
||||
|
||||
If section.key is supplied the value for that single key will be displayed.
|
||||
|
||||
If section.key=value is supplied the value for that single key will be set.
|
||||
|
||||
If section.key=None is supplied the key will be deleted.
|
||||
|
||||
No validation is done to ensure that the supplied section.key is actually used by qmk scripts.
|
||||
"""
|
||||
if not cli.args.configs:
|
||||
# Walk the config tree
|
||||
for section in cli.config:
|
||||
for key in cli.config[section]:
|
||||
print_config(section, key)
|
||||
|
||||
return True
|
||||
|
||||
# Process config_tokens
|
||||
save_config = False
|
||||
|
||||
for argument in cli.args.configs:
|
||||
# Split on space in case they quoted multiple config tokens
|
||||
for config_token in argument.split(' '):
|
||||
# Extract the section, config_key, and value to write from the supplied config_token.
|
||||
if '=' in config_token:
|
||||
key, value = config_token.split('=')
|
||||
else:
|
||||
key = config_token
|
||||
value = None
|
||||
|
||||
if '.' in key:
|
||||
section, config_key = key.split('.', 1)
|
||||
else:
|
||||
section = key
|
||||
config_key = None
|
||||
|
||||
# Validation
|
||||
if config_key and '.' in config_key:
|
||||
cli.log.error('Config keys may not have more than one period! "%s" is not valid.', key)
|
||||
return False
|
||||
|
||||
# Do what the user wants
|
||||
if section and config_key and value:
|
||||
# Write a config key
|
||||
log_string = '%s.%s{fg_cyan}:{fg_reset} %s {fg_cyan}->{fg_reset} %s'
|
||||
if cli.args.read_only:
|
||||
log_string += ' {fg_red}(change not written)'
|
||||
|
||||
cli.echo(log_string, section, config_key, cli.config[section][config_key], value)
|
||||
|
||||
if not cli.args.read_only:
|
||||
if value == 'None':
|
||||
del cli.config[section][config_key]
|
||||
else:
|
||||
cli.config[section][config_key] = value
|
||||
save_config = True
|
||||
|
||||
elif section and config_key:
|
||||
# Display a single key
|
||||
print_config(section, config_key)
|
||||
|
||||
elif section:
|
||||
# Display an entire section
|
||||
for key in cli.config[section]:
|
||||
print_config(section, key)
|
||||
|
||||
# Ending actions
|
||||
if save_config:
|
||||
cli.save_config()
|
||||
|
||||
return True
|
||||
@@ -2,46 +2,77 @@
|
||||
|
||||
Check up for QMK environment.
|
||||
"""
|
||||
import shutil
|
||||
import platform
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
from glob import glob
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.entrypoint('Basic QMK environment checks')
|
||||
def main(cli):
|
||||
@cli.subcommand('Basic QMK environment checks')
|
||||
def doctor(cli):
|
||||
"""Basic QMK environment checks.
|
||||
|
||||
This is currently very simple, it just checks that all the expected binaries are on your system.
|
||||
|
||||
TODO(unclaimed):
|
||||
* [ ] Run the binaries to make sure they work
|
||||
* [ ] Compile a trivial program with each compiler
|
||||
* [ ] Check for udev entries on linux
|
||||
"""
|
||||
cli.log.info('QMK Doctor is checking your environment.')
|
||||
|
||||
# Make sure the basic CLI tools we need are available and can be executed.
|
||||
binaries = ['dfu-programmer', 'avrdude', 'dfu-util', 'avr-gcc', 'arm-none-eabi-gcc']
|
||||
|
||||
cli.log.info('QMK Doctor is Checking your environment')
|
||||
|
||||
binaries += glob('bin/qmk-*')
|
||||
ok = True
|
||||
|
||||
for binary in binaries:
|
||||
res = shutil.which(binary)
|
||||
if res is None:
|
||||
cli.log.error('{fg_red}QMK can\'t find ' + binary + ' in your path')
|
||||
cli.log.error("{fg_red}QMK can't find %s in your path.", binary)
|
||||
ok = False
|
||||
else:
|
||||
try:
|
||||
subprocess.run([binary, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5, check=True)
|
||||
cli.log.info('Found {fg_cyan}%s', binary)
|
||||
except subprocess.CalledProcessError:
|
||||
cli.log.error("{fg_red}Can't run `%s --version`", binary)
|
||||
ok = False
|
||||
|
||||
# Determine our OS and run platform specific tests
|
||||
OS = platform.system()
|
||||
if OS == "Darwin":
|
||||
cli.log.info("Detected {fg_cyan}macOS")
|
||||
elif OS == "Linux":
|
||||
cli.log.info("Detected {fg_cyan}linux")
|
||||
test = 'systemctl list-unit-files | grep enabled | grep -i ModemManager'
|
||||
if os.system(test) == 0:
|
||||
cli.log.warn("{bg_yellow}Detected modem manager. Please disable it if you are using Pro Micros")
|
||||
else:
|
||||
cli.log.info("Assuming {fg_cyan}Windows")
|
||||
|
||||
if OS == "Darwin":
|
||||
cli.log.info("Detected {fg_cyan}macOS.")
|
||||
|
||||
elif OS == "Linux":
|
||||
cli.log.info("Detected {fg_cyan}Linux.")
|
||||
if shutil.which('systemctl'):
|
||||
mm_check = subprocess.run(['systemctl', 'list-unit-files'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=10, universal_newlines=True)
|
||||
if mm_check.returncode == 0:
|
||||
mm = False
|
||||
for line in mm_check.stdout.split('\n'):
|
||||
if 'ModemManager' in line and 'enabled' in line:
|
||||
mm = True
|
||||
|
||||
if mm:
|
||||
cli.log.warn("{bg_yellow}Detected ModemManager. Please disable it if you are using a Pro-Micro.")
|
||||
|
||||
else:
|
||||
cli.log.error('{bg_red}Could not run `systemctl list-unit-files`:')
|
||||
cli.log.error(mm_check.stderr)
|
||||
|
||||
else:
|
||||
cli.log.warn("Can't find systemctl to check for ModemManager.")
|
||||
|
||||
else:
|
||||
cli.log.info("Assuming {fg_cyan}Windows.")
|
||||
|
||||
# Report a summary of our findings to the user
|
||||
if ok:
|
||||
cli.log.info('{fg_green}QMK is ready to go')
|
||||
else:
|
||||
cli.log.info('{fg_yellow}Problems detected, please fix these problems before proceeding.')
|
||||
# FIXME(skullydazed): Link to a document about troubleshooting, or discord or something
|
||||
|
||||
@@ -6,8 +6,8 @@ from milc import cli
|
||||
|
||||
|
||||
@cli.argument('-n', '--name', default='World', help='Name to greet.')
|
||||
@cli.entrypoint('QMK Hello World.')
|
||||
def main(cli):
|
||||
@cli.subcommand('QMK Hello World.')
|
||||
def hello(cli):
|
||||
"""Log a friendly greeting.
|
||||
"""
|
||||
cli.log.info('Hello, %s!', cli.config.general.name)
|
||||
cli.log.info('Hello, %s!', cli.config.hello.name)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
"""QMK CLI JSON Subcommands
|
||||
|
||||
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
|
||||
"""
|
||||
from . import keymap
|
||||
|
||||
@@ -9,10 +9,10 @@ from milc import cli
|
||||
import qmk.keymap
|
||||
|
||||
|
||||
@cli.argument('-o', '--output', help='File to write to')
|
||||
@cli.argument('filename', help='Configurator JSON file')
|
||||
@cli.entrypoint('Create a keymap.c from a QMK Configurator export.')
|
||||
def main(cli):
|
||||
@cli.argument('-o', '--output', arg_only=True, help='File to write to')
|
||||
@cli.argument('filename', arg_only=True, help='Configurator JSON file')
|
||||
@cli.subcommand('Create a keymap.c from a QMK Configurator export.')
|
||||
def json_keymap(cli):
|
||||
"""Generate a keymap.c from a configurator export.
|
||||
|
||||
This command uses the `qmk.keymap` module to generate a keymap.c from a configurator export. The generated keymap is written to stdout, or to a file if -o is provided.
|
||||
@@ -28,8 +28,8 @@ def main(cli):
|
||||
exit(1)
|
||||
|
||||
# Environment processing
|
||||
if cli.config.general.output == ('-'):
|
||||
cli.config.general.output = None
|
||||
if cli.args.output == ('-'):
|
||||
cli.args.output = None
|
||||
|
||||
# Parse the configurator json
|
||||
with open(qmk.path.normpath(cli.args.filename), 'r') as fd:
|
||||
@@ -38,17 +38,17 @@ def main(cli):
|
||||
# Generate the keymap
|
||||
keymap_c = qmk.keymap.generate(user_keymap['keyboard'], user_keymap['layout'], user_keymap['layers'])
|
||||
|
||||
if cli.config.general.output:
|
||||
output_dir = os.path.dirname(cli.config.general.output)
|
||||
if cli.args.output:
|
||||
output_dir = os.path.dirname(cli.args.output)
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
output_file = qmk.path.normpath(cli.config.general.output)
|
||||
output_file = qmk.path.normpath(cli.args.output)
|
||||
with open(output_file, 'w') as keymap_fd:
|
||||
keymap_fd.write(keymap_c)
|
||||
|
||||
cli.log.info('Wrote keymap to %s.', cli.config.general.output)
|
||||
cli.log.info('Wrote keymap to %s.', cli.args.output)
|
||||
|
||||
else:
|
||||
print(keymap_c)
|
||||
|
||||
1
lib/python/qmk/cli/list/__init__.py
Normal file
1
lib/python/qmk/cli/list/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import keyboards
|
||||
26
lib/python/qmk/cli/list/keyboards.py
Normal file
26
lib/python/qmk/cli/list/keyboards.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""List the keyboards currently defined within QMK
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import glob
|
||||
|
||||
from milc import cli
|
||||
|
||||
@cli.subcommand("List the keyboards currently defined within QMK")
|
||||
def list_keyboards(cli):
|
||||
"""List the keyboards currently defined within QMK
|
||||
"""
|
||||
|
||||
base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep
|
||||
kb_path_wildcard = os.path.join(base_path, "**", "rules.mk")
|
||||
|
||||
# find everywhere we have rules.mk where keymaps isn't in the path
|
||||
paths = [path for path in glob.iglob(kb_path_wildcard, recursive=True) if 'keymaps' not in path]
|
||||
|
||||
# strip the keyboard directory path prefix and rules.mk suffix and alphabetize
|
||||
find_name = lambda path: path.replace(base_path, "").replace(os.path.sep + "rules.mk", "")
|
||||
names = sorted(map(find_name, paths))
|
||||
|
||||
for name in names:
|
||||
# We echo instead of cli.log.info to allow easier piping of this output
|
||||
cli.echo(name)
|
||||
1
lib/python/qmk/cli/new/__init__.py
Normal file
1
lib/python/qmk/cli/new/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import keymap
|
||||
40
lib/python/qmk/cli/new/keymap.py
Executable file
40
lib/python/qmk/cli/new/keymap.py
Executable file
@@ -0,0 +1,40 @@
|
||||
"""This script automates the copying of the default keymap into your own keymap.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.argument('-kb', '--keyboard', help='Specify keyboard name. Example: 1upkeyboards/1up60hse')
|
||||
@cli.argument('-km', '--keymap', help='Specify the name for the new keymap directory')
|
||||
@cli.subcommand('Creates a new keymap for the keyboard of your choosing')
|
||||
def new_keymap(cli):
|
||||
"""Creates a new keymap for the keyboard of your choosing.
|
||||
"""
|
||||
# ask for user input if keyboard or keymap was not provided in the command line
|
||||
keyboard = cli.config.new_keymap.keyboard if cli.config.new_keymap.keyboard else input("Keyboard Name: ")
|
||||
keymap = cli.config.new_keymap.keymap if cli.config.new_keymap.keymap else input("Keymap Name: ")
|
||||
|
||||
# generate keymap paths
|
||||
kb_path = os.path.join(os.getcwd(), "keyboards", keyboard)
|
||||
keymap_path_default = os.path.join(kb_path, "keymaps/default")
|
||||
keymap_path = os.path.join(kb_path, "keymaps/%s" % keymap)
|
||||
|
||||
# check directories
|
||||
if not os.path.exists(kb_path):
|
||||
cli.log.error('Keyboard %s does not exist!', kb_path)
|
||||
exit(1)
|
||||
if not os.path.exists(keymap_path_default):
|
||||
cli.log.error('Keyboard default %s does not exist!', keymap_path_default)
|
||||
exit(1)
|
||||
if os.path.exists(keymap_path):
|
||||
cli.log.error('Keymap %s already exists!', keymap_path)
|
||||
exit(1)
|
||||
|
||||
# create user directory with default keymap files
|
||||
shutil.copytree(keymap_path_default, keymap_path, symlinks=True)
|
||||
|
||||
# end message to user
|
||||
cli.log.info("%s keymap directory created in: %s", keymap, keymap_path)
|
||||
cli.log.info("Compile a firmware with your new keymap by typing: \n" + "qmk compile -kb %s -km %s", keyboard, keymap)
|
||||
17
lib/python/qmk/cli/pyformat.py
Executable file
17
lib/python/qmk/cli/pyformat.py
Executable file
@@ -0,0 +1,17 @@
|
||||
"""Format python code according to QMK's style.
|
||||
"""
|
||||
from milc import cli
|
||||
|
||||
import subprocess
|
||||
|
||||
|
||||
@cli.subcommand("Format python code according to QMK's style.")
|
||||
def pyformat(cli):
|
||||
"""Format python code according to QMK's style.
|
||||
"""
|
||||
try:
|
||||
subprocess.run(['yapf', '-vv', '-ri', 'bin/qmk', 'lib/python'], check=True)
|
||||
cli.log.info('Successfully formatted the python code in `bin/qmk` and `lib/python`.')
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
cli.log.error('Error formatting python code!')
|
||||
20
lib/python/qmk/cli/pytest.py
Normal file
20
lib/python/qmk/cli/pytest.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""QMK Python Unit Tests
|
||||
|
||||
QMK script to run unit and integration tests against our python code.
|
||||
"""
|
||||
import sys
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.subcommand('QMK Python Unit Tests')
|
||||
def pytest(cli):
|
||||
"""Use nose2 to run unittests
|
||||
"""
|
||||
try:
|
||||
import nose2
|
||||
|
||||
except ImportError:
|
||||
cli.log.error('Could not import nose2! Please install it with {fg_cyan}pip3 install nose2')
|
||||
return False
|
||||
|
||||
nose2.discover(argv=['nose2', '-v'])
|
||||
@@ -1,6 +1,10 @@
|
||||
"""Functions that help us work with files and folders.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from pkgutil import walk_packages
|
||||
|
||||
from qmk.errors import NoSuchKeyboardError
|
||||
|
||||
|
||||
def keymap(keyboard):
|
||||
|
||||
0
lib/python/qmk/tests/__init__.py
Normal file
0
lib/python/qmk/tests/__init__.py
Normal file
9
lib/python/qmk/tests/attrdict.py
Normal file
9
lib/python/qmk/tests/attrdict.py
Normal file
@@ -0,0 +1,9 @@
|
||||
class AttrDict(dict):
|
||||
"""A dictionary that can be accessed by attributes.
|
||||
|
||||
This should only be used to mock objects for unit testing. Please do not use this outside of qmk.tests.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AttrDict, self).__init__(*args, **kwargs)
|
||||
self.__dict__ = self
|
||||
6
lib/python/qmk/tests/onekey_export.json
Normal file
6
lib/python/qmk/tests/onekey_export.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"keyboard":"handwired/onekey/pytest",
|
||||
"keymap":"pytest_unittest",
|
||||
"layout":"LAYOUT",
|
||||
"layers":[["KC_A"]]
|
||||
}
|
||||
47
lib/python/qmk/tests/test_cli_commands.py
Normal file
47
lib/python/qmk/tests/test_cli_commands.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import subprocess
|
||||
|
||||
|
||||
def check_subcommand(command, *args):
|
||||
cmd = ['bin/qmk', command] + list(args)
|
||||
return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
||||
|
||||
|
||||
def test_cformat():
|
||||
assert check_subcommand('cformat', 'tmk_core/common/backlight.c').returncode == 0
|
||||
|
||||
|
||||
def test_compile():
|
||||
assert check_subcommand('compile', '-kb', 'handwired/onekey/pytest', '-km', 'default').returncode == 0
|
||||
|
||||
|
||||
def test_config():
|
||||
result = check_subcommand('config')
|
||||
assert result.returncode == 0
|
||||
assert 'general.color' in result.stdout
|
||||
|
||||
|
||||
def test_doctor():
|
||||
result = check_subcommand('doctor')
|
||||
assert result.returncode == 0
|
||||
assert 'QMK Doctor is checking your environment.' in result.stderr
|
||||
assert 'QMK is ready to go' in result.stderr
|
||||
|
||||
|
||||
def test_hello():
|
||||
result = check_subcommand('hello')
|
||||
assert result.returncode == 0
|
||||
assert 'Hello,' in result.stderr
|
||||
|
||||
|
||||
def test_pyformat():
|
||||
result = check_subcommand('pyformat')
|
||||
assert result.returncode == 0
|
||||
assert 'Successfully formatted the python code' in result.stderr
|
||||
|
||||
|
||||
def test_list_keyboards():
|
||||
result = check_subcommand('list-keyboards')
|
||||
assert result.returncode == 0
|
||||
# check to see if a known keyboard is returned
|
||||
# this will fail if handwired/onekey/pytest is removed
|
||||
assert 'handwired/onekey/pytest' in result.stdout
|
||||
8
lib/python/qmk/tests/test_qmk_errors.py
Normal file
8
lib/python/qmk/tests/test_qmk_errors.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from qmk.errors import NoSuchKeyboardError
|
||||
|
||||
|
||||
def test_NoSuchKeyboardError():
|
||||
try:
|
||||
raise NoSuchKeyboardError("test message")
|
||||
except NoSuchKeyboardError as e:
|
||||
assert e.message == 'test message'
|
||||
19
lib/python/qmk/tests/test_qmk_keymap.py
Normal file
19
lib/python/qmk/tests/test_qmk_keymap.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import qmk.keymap
|
||||
|
||||
|
||||
def test_template_onekey_proton_c():
|
||||
templ = qmk.keymap.template('handwired/onekey/proton_c')
|
||||
assert templ == qmk.keymap.DEFAULT_KEYMAP_C
|
||||
|
||||
|
||||
def test_template_onekey_pytest():
|
||||
templ = qmk.keymap.template('handwired/onekey/pytest')
|
||||
assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {__KEYMAP_GOES_HERE__};\n'
|
||||
|
||||
|
||||
def test_generate_onekey_pytest():
|
||||
templ = qmk.keymap.generate('handwired/onekey/pytest', 'LAYOUT', [['KC_A']])
|
||||
assert templ == 'const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT(KC_A)};\n'
|
||||
|
||||
|
||||
# FIXME(skullydazed): Add a test for qmk.keymap.write that mocks up an FD.
|
||||
13
lib/python/qmk/tests/test_qmk_path.py
Normal file
13
lib/python/qmk/tests/test_qmk_path.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import os
|
||||
|
||||
import qmk.path
|
||||
|
||||
|
||||
def test_keymap_onekey_pytest():
|
||||
path = qmk.path.keymap('handwired/onekey/pytest')
|
||||
assert path == 'keyboards/handwired/onekey/keymaps'
|
||||
|
||||
|
||||
def test_normpath():
|
||||
path = qmk.path.normpath('lib/python')
|
||||
assert path == os.environ['ORIG_CWD'] + '/lib/python'
|
||||
@@ -76,6 +76,11 @@ define GENERATE_MSG_MAKE_TEST
|
||||
endef
|
||||
MSG_MAKE_TEST = $(eval $(call GENERATE_MSG_MAKE_TEST))$(MSG_MAKE_TEST_ACTUAL)
|
||||
MSG_TEST = Testing $(BOLD)$(TEST_NAME)$(NO_COLOR)
|
||||
define GENERATE_MSG_AVAILABLE_KEYMAPS
|
||||
MSG_AVAILABLE_KEYMAPS_ACTUAL := Available keymaps for $(BOLD)$$(CURRENT_KB)$(NO_COLOR):
|
||||
endef
|
||||
MSG_AVAILABLE_KEYMAPS = $(eval $(call GENERATE_MSG_AVAILABLE_KEYMAPS))$(MSG_AVAILABLE_KEYMAPS_ACTUAL)
|
||||
|
||||
MSG_CHECK_FILESIZE = Checking file size of $(TARGET).hex
|
||||
MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT_SIZE)/$(MAX_SIZE) ($(OVER_SIZE) bytes over)\n
|
||||
MSG_FILE_TOO_SMALL = The firmware is too small! $(CURRENT_SIZE)/$(MAX_SIZE)\n
|
||||
@@ -87,3 +92,4 @@ MSG_PYTHON_MISSING = $(WARN_COLOR)WARNING:$(NO_COLOR)\n \
|
||||
Please run $(BOLD)util/qmk_install.sh$(NO_COLOR) to install all the dependencies QMK requires.\n\n
|
||||
MSG_FLASH_BOOTLOADER = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's bootloader is not specified or is not supported by the \":flash\" target at this time.\n\n
|
||||
MSG_FLASH_ARCH = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's architecture is not supported by the \":flash\" target at this time.\n\n
|
||||
MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) Bootloader not found. Trying again in 5s.\n
|
||||
|
||||
@@ -36,7 +36,11 @@ RGB hsv_to_rgb(HSV hsv) {
|
||||
|
||||
h = hsv.h;
|
||||
s = hsv.s;
|
||||
#ifdef USE_CIE1931_CURVE
|
||||
v = pgm_read_byte(&CIE1931_CURVE[hsv.v]);
|
||||
#else
|
||||
v = hsv.v;
|
||||
#endif
|
||||
|
||||
region = h * 6 / 255;
|
||||
remainder = (h * 2 - region * 85) * 3;
|
||||
@@ -79,11 +83,5 @@ RGB hsv_to_rgb(HSV hsv) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_CIE1931_CURVE
|
||||
rgb.r = pgm_read_byte(&CIE1931_CURVE[rgb.r]);
|
||||
rgb.g = pgm_read_byte(&CIE1931_CURVE[rgb.g]);
|
||||
rgb.b = pgm_read_byte(&CIE1931_CURVE[rgb.b]);
|
||||
#endif
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
// LEDs (only D5/C13 uses an actual LED)
|
||||
# ifdef CONVERT_TO_PROTON_C_RXLED
|
||||
# define D5 PAL_LINE(GPIOC, 13)
|
||||
# define D5 PAL_LINE(GPIOC, 14)
|
||||
# define B0 PAL_LINE(GPIOC, 13)
|
||||
# else
|
||||
# define D5 PAL_LINE(GPIOC, 13)
|
||||
@@ -303,6 +303,25 @@
|
||||
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
|
||||
sei(); \
|
||||
} while (0)
|
||||
# elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
|
||||
# define SERIAL_UART_BAUD 115200
|
||||
# define SERIAL_UART_DATA UDR1
|
||||
/* UBRR should result in ~16 and set UCSR1A = _BV(U2X1) as per rn42 documentation. HC05 needs baudrate configured accordingly */
|
||||
# define SERIAL_UART_UBRR (F_CPU / (8UL * SERIAL_UART_BAUD) - 1)
|
||||
# define SERIAL_UART_RXD_VECT USART1_RX_vect
|
||||
# define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
|
||||
# define SERIAL_UART_INIT() do { \
|
||||
UCSR1A = _BV(U2X1); \
|
||||
/* baud rate */ \
|
||||
UBRR1L = SERIAL_UART_UBRR; \
|
||||
/* baud rate */ \
|
||||
UBRR1H = SERIAL_UART_UBRR >> 8; \
|
||||
/* enable TX */ \
|
||||
UCSR1B = _BV(TXEN1); \
|
||||
/* 8-bit data */ \
|
||||
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
|
||||
sei(); \
|
||||
} while(0)
|
||||
# else
|
||||
# error "USART configuration is needed."
|
||||
# endif
|
||||
|
||||
71
quantum/dip_switch.c
Normal file
71
quantum/dip_switch.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
|
||||
* Copyright 2019 Drashna Jaelre (Christopher Courtney) <drashna@live.com>
|
||||
*
|
||||
* 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 "dip_switch.h"
|
||||
|
||||
// for memcpy
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if !defined(DIP_SWITCH_PINS)
|
||||
# error "No DIP switch pads defined by DIP_SWITCH_PINS"
|
||||
#endif
|
||||
|
||||
#define NUMBER_OF_DIP_SWITCHES (sizeof(dip_switch_pad)/sizeof(pin_t))
|
||||
static pin_t dip_switch_pad[] = DIP_SWITCH_PINS;
|
||||
static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = { 0 };
|
||||
static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = { 0 };
|
||||
|
||||
|
||||
__attribute__((weak))
|
||||
void dip_switch_update_user(uint8_t index, bool active) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void dip_switch_update_kb(uint8_t index, bool active) { dip_switch_update_user(index, active); }
|
||||
|
||||
__attribute__((weak))
|
||||
void dip_switch_update_mask_user(uint32_t state) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void dip_switch_update_mask_kb(uint32_t state) { dip_switch_update_mask_user(state); }
|
||||
|
||||
void dip_switch_init(void) {
|
||||
for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) {
|
||||
setPinInputHigh(dip_switch_pad[i]);
|
||||
}
|
||||
dip_switch_read(true);
|
||||
}
|
||||
|
||||
|
||||
void dip_switch_read(bool forced) {
|
||||
bool has_dip_state_changed = false;
|
||||
uint32_t dip_switch_mask = 0;
|
||||
|
||||
for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) {
|
||||
dip_switch_state[i] = !readPin(dip_switch_pad[i]);
|
||||
dip_switch_mask |= dip_switch_state[i] << i;
|
||||
if (last_dip_switch_state[i] ^ dip_switch_state[i] || forced) {
|
||||
has_dip_state_changed = true;
|
||||
dip_switch_update_kb(i, dip_switch_state[i]);
|
||||
}
|
||||
}
|
||||
if (has_dip_state_changed) {
|
||||
dip_switch_update_mask_kb(dip_switch_mask);
|
||||
}
|
||||
memcpy(last_dip_switch_state, dip_switch_state, sizeof(&dip_switch_state));
|
||||
}
|
||||
29
quantum/dip_switch.h
Normal file
29
quantum/dip_switch.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
|
||||
* Copyright 2018 Drashna Jaelre (Christopher Courtney) <drashna@live.com>
|
||||
*
|
||||
* 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"
|
||||
|
||||
void dip_switch_update_kb(uint8_t index, bool active);
|
||||
void dip_switch_update_user(uint8_t index, bool active);
|
||||
void dip_switch_update_mask_user(uint32_t state);
|
||||
void dip_switch_update_mask_kb(uint32_t state);
|
||||
|
||||
void dip_switch_init(void);
|
||||
void dip_switch_read(bool forced);
|
||||
@@ -40,8 +40,10 @@ static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1,
|
||||
static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
// slave half encoders come over as second set of encoders
|
||||
// right half encoders come over as second set of encoders
|
||||
static int8_t encoder_value[NUMBER_OF_ENCODERS * 2] = {0};
|
||||
// row offsets for each hand
|
||||
static uint8_t thisHand, thatHand;
|
||||
#else
|
||||
static int8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
|
||||
#endif
|
||||
@@ -68,20 +70,33 @@ void encoder_init(void) {
|
||||
|
||||
encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
|
||||
}
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS;
|
||||
thatHand = NUMBER_OF_ENCODERS - thisHand;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void encoder_update(int8_t index, uint8_t state) {
|
||||
encoder_value[index] += encoder_LUT[state & 0xF];
|
||||
if (encoder_value[index] >= ENCODER_RESOLUTION) {
|
||||
encoder_update_kb(index, false);
|
||||
}
|
||||
if (encoder_value[index] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
|
||||
encoder_update_kb(index, true);
|
||||
}
|
||||
encoder_value[index] %= ENCODER_RESOLUTION;
|
||||
}
|
||||
|
||||
void encoder_read(void) {
|
||||
for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
|
||||
encoder_state[i] <<= 2;
|
||||
encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
|
||||
encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF];
|
||||
if (encoder_value[i] >= ENCODER_RESOLUTION) {
|
||||
encoder_update_kb(i, false);
|
||||
}
|
||||
if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
|
||||
encoder_update_kb(i, true);
|
||||
}
|
||||
encoder_value[i] %= ENCODER_RESOLUTION;
|
||||
#if SPLIT_KEYBOARD
|
||||
encoder_update(i + thisHand, encoder_state[i]);
|
||||
#else
|
||||
encoder_update(i, encoder_state[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,14 +105,7 @@ void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, encoder_state
|
||||
|
||||
void encoder_update_raw(uint8_t* slave_state) {
|
||||
for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
|
||||
encoder_value[NUMBER_OF_ENCODERS + i] += encoder_LUT[slave_state[i] & 0xF];
|
||||
if (encoder_value[NUMBER_OF_ENCODERS + i] >= ENCODER_RESOLUTION) {
|
||||
encoder_update_kb(NUMBER_OF_ENCODERS + i, false);
|
||||
}
|
||||
if (encoder_value[NUMBER_OF_ENCODERS + i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
|
||||
encoder_update_kb(NUMBER_OF_ENCODERS + i, true);
|
||||
}
|
||||
encoder_value[NUMBER_OF_ENCODERS + i] %= ENCODER_RESOLUTION;
|
||||
encoder_update(i + thatHand, slave_state[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "action.h"
|
||||
#include "action_macro.h"
|
||||
#include "debug.h"
|
||||
#include "backlight.h"
|
||||
#include "quantum.h"
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
# include "process_midi.h"
|
||||
#endif
|
||||
|
||||
@@ -78,35 +78,36 @@
|
||||
#define IT_MINS KC_SLSH // - and _
|
||||
|
||||
// shifted characters
|
||||
#define IT_PIPE LSFT(IT_BKSL) // °
|
||||
#define IT_EXLM LSFT(KC_1) // !
|
||||
#define IT_DQOT LSFT(KC_2) // "
|
||||
#define IT_STRL LSFT(KC_3) // £
|
||||
#define IT_DLR LSFT(KC_4) // $
|
||||
#define IT_PERC LSFT(KC_5) // %
|
||||
#define IT_AMPR LSFT(KC_6) // &
|
||||
#define IT_SLSH LSFT(KC_7) // /
|
||||
#define IT_LPRN LSFT(KC_8) // (
|
||||
#define IT_RPRN LSFT(KC_9) // )
|
||||
#define IT_EQL LSFT(KC_0) // =
|
||||
#define IT_QST LSFT(IT_APOS) // ?
|
||||
#define IT_CRC LSFT(IT_IACC) // ^
|
||||
#define IT_ASTR LSFT(IT_PLUS) // *
|
||||
#define IT_MORE LSFT(IT_LESS) // >
|
||||
#define IT_COLN LSFT(IT_DOT) // :
|
||||
#define IT_SCLN LSFT(IT_COMM) // ;
|
||||
#define IT_UNDS LSFT(IT_MINS) // _
|
||||
#define IT_DEGR LSFT(IT_AACC) // °
|
||||
#define IT_EXLM LSFT(KC_1) // !
|
||||
#define IT_DQOT LSFT(KC_2) // "
|
||||
#define IT_STRL LSFT(KC_3) // £
|
||||
#define IT_DLR LSFT(KC_4) // $
|
||||
#define IT_PERC LSFT(KC_5) // %
|
||||
#define IT_AMPR LSFT(KC_6) // &
|
||||
#define IT_SLSH LSFT(KC_7) // /
|
||||
#define IT_LPRN LSFT(KC_8) // (
|
||||
#define IT_RPRN LSFT(KC_9) // )
|
||||
#define IT_EQL LSFT(KC_0) // =
|
||||
#define IT_QST LSFT(IT_APOS) // ?
|
||||
#define IT_CRC LSFT(IT_IACC) // ^
|
||||
#define IT_ASTR LSFT(IT_PLUS) // *
|
||||
#define IT_MORE LSFT(IT_LESS) // >
|
||||
#define IT_COLN LSFT(IT_DOT) // :
|
||||
#define IT_SCLN LSFT(IT_COMM) // ;
|
||||
#define IT_UNDS LSFT(IT_MINS) // _
|
||||
|
||||
// Alt Gr-ed characters
|
||||
#define IT_LCBR ALGR(KC_7) // {
|
||||
#define IT_LBRC ALGR(IT_EACC) // [
|
||||
#define IT_RBRC ALGR(IT_PLUS) // ]
|
||||
#define IT_RCBR ALGR(KC_0) // }
|
||||
#define IT_AT ALGR(IT_OACC) // @
|
||||
#define IT_EURO ALGR(KC_E) // €
|
||||
#define IT_PIPE LSFT(IT_BKSL) // |
|
||||
#define IT_SHRP ALGR(IT_AACC) // #
|
||||
#define IT_LCBR ALGR(KC_7) // {
|
||||
#define IT_LBRC ALGR(IT_EACC) // [
|
||||
#define IT_RBRC ALGR(IT_PLUS) // ]
|
||||
#define IT_RCBR ALGR(KC_0) // }
|
||||
#define IT_AT ALGR(IT_OACC) // @
|
||||
#define IT_EURO ALGR(KC_E) // €
|
||||
#define IT_PIPE LSFT(IT_BSLS) // |
|
||||
#define IT_SHRP ALGR(IT_AACC) // #
|
||||
|
||||
#define IT_X_PLUS X_RBRACKET // #
|
||||
// Deprecated
|
||||
#define IT_X_PLUS X_RBRACKET // #
|
||||
|
||||
#endif
|
||||
|
||||
113
quantum/keymap_extras/keymap_italian_osx_ansi.h
Normal file
113
quantum/keymap_extras/keymap_italian_osx_ansi.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Copyright 2015-2016 Matthias Schmidtt
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is a clone of quantum/keymap_extra/keymap_italian.h intended to be used with Apple devices
|
||||
|
||||
#ifndef KEYMAP_ITALIAN
|
||||
#define KEYMAP_ITALIAN
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
// normal characters
|
||||
#define IT_A KC_A
|
||||
#define IT_B KC_B
|
||||
#define IT_C KC_C
|
||||
#define IT_D KC_D
|
||||
#define IT_E KC_E
|
||||
#define IT_F KC_F
|
||||
#define IT_G KC_G
|
||||
#define IT_H KC_H
|
||||
#define IT_I KC_I
|
||||
#define IT_J KC_J
|
||||
#define IT_K KC_K
|
||||
#define IT_L KC_L
|
||||
#define IT_M KC_M
|
||||
#define IT_N KC_N
|
||||
#define IT_O KC_O
|
||||
#define IT_P KC_P
|
||||
#define IT_Q KC_Q
|
||||
#define IT_R KC_R
|
||||
#define IT_S KC_S
|
||||
#define IT_T KC_T
|
||||
#define IT_U KC_U
|
||||
#define IT_V KC_V
|
||||
#define IT_W KC_W
|
||||
#define IT_X KC_X
|
||||
#define IT_Y KC_Y
|
||||
#define IT_Z KC_Z
|
||||
|
||||
#define IT_0 KC_0
|
||||
#define IT_1 KC_1
|
||||
#define IT_2 KC_2
|
||||
#define IT_3 KC_3
|
||||
#define IT_4 KC_4
|
||||
#define IT_5 KC_5
|
||||
#define IT_6 KC_6
|
||||
#define IT_7 KC_7
|
||||
#define IT_8 KC_8
|
||||
#define IT_9 KC_9
|
||||
|
||||
// punctuation
|
||||
#define IT_DOT KC_DOT // . and :
|
||||
#define IT_COMM KC_COMM // , and ;
|
||||
#define IT_APOS KC_MINS // ' and ?
|
||||
#define IT_BSLS KC_NUBS // \ and |
|
||||
#define IT_LESS KC_GRV // < and >
|
||||
#define IT_MINS KC_SLSH // - and _
|
||||
|
||||
// accented vowels (regular, with shift, with option, with option and shift)
|
||||
#define IT_EACC KC_LBRC // è, é, [, {
|
||||
#define IT_PLUS KC_RBRC // +, *, ], }
|
||||
#define IT_OACC KC_SCLN // ò, ç, @, Ç
|
||||
#define IT_AACC KC_QUOT // à, °, #, ∞
|
||||
#define IT_UACC KC_BSLS // ù, §, ¶, ◊
|
||||
#define IT_IACC KC_EQL // ì, ^, ˆ, ±
|
||||
|
||||
// shifted characters
|
||||
#define IT_EXLM LSFT(KC_1) // !
|
||||
#define IT_DQOT LSFT(KC_2) // "
|
||||
#define IT_STRL LSFT(KC_3) // £
|
||||
#define IT_DLR LSFT(KC_4) // $
|
||||
#define IT_PERC LSFT(KC_5) // %
|
||||
#define IT_AMPR LSFT(KC_6) // &
|
||||
#define IT_SLSH LSFT(KC_7) // /
|
||||
#define IT_LPRN LSFT(KC_8) // (
|
||||
#define IT_RPRN LSFT(KC_9) // )
|
||||
#define IT_EQL LSFT(KC_0) // =
|
||||
#define IT_DEGR LSFT(IT_AACC) // °
|
||||
#define IT_QST LSFT(IT_APOS) // ?
|
||||
#define IT_CRC LSFT(IT_IACC) // ^
|
||||
#define IT_ASTR LSFT(IT_PLUS) // *
|
||||
#define IT_MORE LSFT(IT_LESS) // >
|
||||
#define IT_COLN LSFT(IT_DOT) // :
|
||||
#define IT_SCLN LSFT(IT_COMM) // ;
|
||||
#define IT_UNDS LSFT(IT_MINS) // _
|
||||
#define IT_LCBR LSFT(IT_LBRC) // {
|
||||
#define IT_RCBR LSFT(IT_RBRC) // }
|
||||
#define IT_PIPE LSFT(IT_BSLS) // |
|
||||
|
||||
// Alt -ed characters
|
||||
#define IT_LBRC LALT(IT_EACC) // [
|
||||
#define IT_RBRC LALT(IT_PLUS) // ]
|
||||
#define IT_AT LALT(IT_OACC) // @
|
||||
#define IT_EURO LALT(KC_E) // €
|
||||
#define IT_SHRP LALT(IT_AACC ) // #
|
||||
#define IT_ACUT LALT(KC_8) // ´
|
||||
#define IT_GRAVE LALT(KC_9) // `
|
||||
#define IT_TILDE LALT(KC_5) // ~
|
||||
#define IT_PLMN LALT(LSFT(IT_IACC)) // ±
|
||||
|
||||
#endif
|
||||
113
quantum/keymap_extras/keymap_italian_osx_iso.h
Normal file
113
quantum/keymap_extras/keymap_italian_osx_iso.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Copyright 2015-2016 Matthias Schmidtt
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// This is a clone of quantum/keymap_extra/keymap_italian.h intended to be used with Apple devices
|
||||
|
||||
#ifndef KEYMAP_ITALIAN
|
||||
#define KEYMAP_ITALIAN
|
||||
|
||||
#include "keymap.h"
|
||||
|
||||
// normal characters
|
||||
#define IT_A KC_A
|
||||
#define IT_B KC_B
|
||||
#define IT_C KC_C
|
||||
#define IT_D KC_D
|
||||
#define IT_E KC_E
|
||||
#define IT_F KC_F
|
||||
#define IT_G KC_G
|
||||
#define IT_H KC_H
|
||||
#define IT_I KC_I
|
||||
#define IT_J KC_J
|
||||
#define IT_K KC_K
|
||||
#define IT_L KC_L
|
||||
#define IT_M KC_M
|
||||
#define IT_N KC_N
|
||||
#define IT_O KC_O
|
||||
#define IT_P KC_P
|
||||
#define IT_Q KC_Q
|
||||
#define IT_R KC_R
|
||||
#define IT_S KC_S
|
||||
#define IT_T KC_T
|
||||
#define IT_U KC_U
|
||||
#define IT_V KC_V
|
||||
#define IT_W KC_W
|
||||
#define IT_X KC_X
|
||||
#define IT_Y KC_Y
|
||||
#define IT_Z KC_Z
|
||||
|
||||
#define IT_0 KC_0
|
||||
#define IT_1 KC_1
|
||||
#define IT_2 KC_2
|
||||
#define IT_3 KC_3
|
||||
#define IT_4 KC_4
|
||||
#define IT_5 KC_5
|
||||
#define IT_6 KC_6
|
||||
#define IT_7 KC_7
|
||||
#define IT_8 KC_8
|
||||
#define IT_9 KC_9
|
||||
|
||||
// punctuation
|
||||
#define IT_DOT KC_DOT // . and :
|
||||
#define IT_COMM KC_COMM // , and ;
|
||||
#define IT_APOS KC_MINS // ' and ?
|
||||
#define IT_BSLS KC_GRV // \ and |
|
||||
#define IT_LESS KC_NUBS// < and >
|
||||
#define IT_MINS KC_SLSH // - and _
|
||||
|
||||
// accented vowels (regular, with shift, with option, with option and shift)
|
||||
#define IT_EACC KC_LBRC // è, é, [, {
|
||||
#define IT_PLUS KC_RBRC // +, *, ], }
|
||||
#define IT_OACC KC_SCLN // ò, ç, @, Ç
|
||||
#define IT_AACC KC_QUOT // à, °, #, ∞
|
||||
#define IT_UACC KC_BSLS // ù, §, ¶, ◊
|
||||
#define IT_IACC KC_EQL // ì, ^, ˆ, ±
|
||||
|
||||
// shifted characters
|
||||
#define IT_EXLM LSFT(KC_1) // !
|
||||
#define IT_DQOT LSFT(KC_2) // "
|
||||
#define IT_STRL LSFT(KC_3) // £
|
||||
#define IT_DLR LSFT(KC_4) // $
|
||||
#define IT_PERC LSFT(KC_5) // %
|
||||
#define IT_AMPR LSFT(KC_6) // &
|
||||
#define IT_SLSH LSFT(KC_7) // /
|
||||
#define IT_LPRN LSFT(KC_8) // (
|
||||
#define IT_RPRN LSFT(KC_9) // )
|
||||
#define IT_EQL LSFT(KC_0) // =
|
||||
#define IT_DEGR LSFT(IT_AACC) // °
|
||||
#define IT_QST LSFT(IT_APOS) // ?
|
||||
#define IT_CRC LSFT(IT_IACC) // ^
|
||||
#define IT_ASTR LSFT(IT_PLUS) // *
|
||||
#define IT_MORE LSFT(IT_LESS) // >
|
||||
#define IT_COLN LSFT(IT_DOT) // :
|
||||
#define IT_SCLN LSFT(IT_COMM) // ;
|
||||
#define IT_UNDS LSFT(IT_MINS) // _
|
||||
#define IT_LCBR LSFT(IT_LBRC) // {
|
||||
#define IT_RCBR LSFT(IT_RBRC) // }
|
||||
#define IT_PIPE LSFT(IT_BSLS) // |
|
||||
|
||||
// Alt -ed characters
|
||||
#define IT_LBRC LALT(IT_EACC) // [
|
||||
#define IT_RBRC LALT(IT_PLUS) // ]
|
||||
#define IT_AT LALT(IT_OACC) // @
|
||||
#define IT_EURO LALT(KC_E) // €
|
||||
#define IT_SHRP LALT(IT_AACC ) // #
|
||||
#define IT_ACUT LALT(KC_8) // ´
|
||||
#define IT_GRAVE LALT(KC_9) // `
|
||||
#define IT_TILDE LALT(KC_5) // ~
|
||||
#define IT_PLMN LALT(LSFT(IT_IACC)) // ±
|
||||
|
||||
#endif
|
||||
@@ -15,14 +15,50 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "led_tables.h"
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifdef USE_CIE1931_CURVE
|
||||
// Lightness curve using the CIE 1931 lightness formula
|
||||
// Generated by the python script provided in http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||
const uint8_t CIE1931_CURVE[256] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 45, 46,
|
||||
47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 96, 97, 99, 100, 101, 103, 104, 106, 107, 108, 110, 111, 113, 114, 116, 118, 119, 121, 122, 124, 125, 127, 129, 130, 132, 134, 135, 137, 139, 141, 142, 144, 146, 148, 149, 151, 153, 155, 157, 159, 161, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 185, 187, 189, 191, 193, 195, 197, 200, 202, 204, 206, 208, 211, 213, 215, 218, 220, 222, 225, 227, 230, 232, 234, 237, 239, 242, 244, 247, 249, 252, 255};
|
||||
const uint8_t CIE1931_CURVE[256] PROGMEM = {
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
|
||||
4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12,
|
||||
12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17,
|
||||
18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25,
|
||||
26, 26, 27, 27, 28, 29, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35,
|
||||
36, 36, 37, 38, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47,
|
||||
48, 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
|
||||
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79,
|
||||
80, 81, 83, 84, 85, 86, 88, 89, 90, 91, 93, 94, 95, 97, 98, 100,
|
||||
101, 102, 104, 105, 107, 108, 109, 111, 112, 114, 115, 117, 119, 120, 122, 123,
|
||||
125, 126, 128, 130, 131, 133, 135, 136, 138, 140, 142, 143, 145, 147, 149, 150,
|
||||
152, 154, 156, 158, 160, 162, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181,
|
||||
183, 186, 188, 190, 192, 194, 196, 198, 201, 203, 205, 207, 209, 212, 214, 216,
|
||||
219, 221, 223, 226, 228, 231, 233, 235, 238, 240, 243, 245, 248, 250, 253, 255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_LED_BREATHING_TABLE
|
||||
const uint8_t LED_BREATHING_TABLE[256] PROGMEM = {0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
|
||||
255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131, 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0};
|
||||
const uint8_t LED_BREATHING_TABLE[256] PROGMEM = {
|
||||
0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
|
||||
10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
|
||||
37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
|
||||
79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
|
||||
127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173,
|
||||
176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215,
|
||||
218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244,
|
||||
245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
|
||||
255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246,
|
||||
245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220,
|
||||
218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179,
|
||||
176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131,
|
||||
128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82,
|
||||
79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
|
||||
37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
|
||||
10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0
|
||||
};
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -36,7 +36,7 @@ ifneq ($(findstring STM32F303, $(MCU)),)
|
||||
DFU_SUFFIX_ARGS = -p DF11 -v 0483
|
||||
endif
|
||||
|
||||
ifneq (,$(filter $(MCU),atmega32u2 atmega32u4 at90usb1286))
|
||||
ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb1286))
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency in Hz. You can then use this symbol in your source code to
|
||||
@@ -91,3 +91,18 @@ ifneq (,$(filter $(MCU),atmega32a))
|
||||
# Programming options
|
||||
PROGRAM_CMD ?= ./util/atmega32a_program.py $(TARGET).hex
|
||||
endif
|
||||
|
||||
ifneq (,$(filter $(MCU),atmega328p))
|
||||
PROTOCOL = VUSB
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency in Hz. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
F_CPU ?= 16000000
|
||||
|
||||
# unsupported features for now
|
||||
NO_UART ?= yes
|
||||
NO_SUSPEND_POWER_DOWN ?= yes
|
||||
endif
|
||||
|
||||
@@ -71,7 +71,7 @@ void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_dat
|
||||
if (state->count == 1) {
|
||||
register_code16(pair->kc);
|
||||
} else if (state->count == 2) {
|
||||
layer_move(pair->layer);
|
||||
pair->layer_function(pair->layer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,13 +56,19 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint16_t kc;
|
||||
uint8_t layer;
|
||||
void (*layer_function)(uint8_t);
|
||||
} qk_tap_dance_dual_role_t;
|
||||
|
||||
# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \
|
||||
{ .fn = {qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset}, .user_data = (void *)&((qk_tap_dance_pair_t){kc1, kc2}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) \
|
||||
{ .fn = {qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer}), }
|
||||
{ .fn = { qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset }, .user_data = (void *)&((qk_tap_dance_dual_role_t) { kc, layer, layer_move }), }
|
||||
|
||||
# define ACTION_TAP_DANCE_TOGGLE_LAYER(kc, layer) \
|
||||
{ .fn = { NULL, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset }, .user_data = (void *)&((qk_tap_dance_dual_role_t) { kc, layer, layer_invert }), }
|
||||
|
||||
# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) ACTION_TAP_DANCE_DUAL_ROLE(kc, layer)
|
||||
|
||||
# define ACTION_TAP_DANCE_FN(user_fn) \
|
||||
{ .fn = {NULL, user_fn, NULL}, .user_data = NULL, }
|
||||
@@ -73,6 +79,8 @@ typedef struct {
|
||||
# define ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term) \
|
||||
{ .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, .custom_tapping_term = tap_specific_tapping_term, }
|
||||
|
||||
|
||||
|
||||
extern qk_tap_dance_action_t tap_dance_actions[];
|
||||
|
||||
/* To be used internally */
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
# define BREATHING_PERIOD 6
|
||||
#endif
|
||||
|
||||
#include "backlight.h"
|
||||
extern backlight_config_t backlight_config;
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
extern backlight_config_t backlight_config;
|
||||
#endif
|
||||
|
||||
#ifdef FAUXCLICKY_ENABLE
|
||||
# include "fauxclicky.h"
|
||||
@@ -55,6 +57,10 @@ extern backlight_config_t backlight_config;
|
||||
# include "encoder.h"
|
||||
#endif
|
||||
|
||||
#ifdef WEBUSB_ENABLE
|
||||
# include "webusb.h"
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
# ifndef GOODBYE_SONG
|
||||
# define GOODBYE_SONG SONG(GOODBYE_SOUND)
|
||||
@@ -89,44 +95,28 @@ static void do_code16(uint16_t code, void (*f)(uint8_t)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (code & QK_LCTL) f(KC_LCTL);
|
||||
if (code & QK_LSFT) f(KC_LSFT);
|
||||
if (code & QK_LALT) f(KC_LALT);
|
||||
if (code & QK_LGUI) f(KC_LGUI);
|
||||
uint8_t mods_to_send = 0;
|
||||
|
||||
if (code < QK_RMODS_MIN) return;
|
||||
if (code & QK_RMODS_MIN) { // Right mod flag is set
|
||||
if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL);
|
||||
if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT);
|
||||
if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT);
|
||||
if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RGUI);
|
||||
} else {
|
||||
if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LCTL);
|
||||
if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LSFT);
|
||||
if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LALT);
|
||||
if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI);
|
||||
}
|
||||
|
||||
if (code & QK_RCTL) f(KC_RCTL);
|
||||
if (code & QK_RSFT) f(KC_RSFT);
|
||||
if (code & QK_RALT) f(KC_RALT);
|
||||
if (code & QK_RGUI) f(KC_RGUI);
|
||||
}
|
||||
|
||||
static inline void qk_register_weak_mods(uint8_t kc) {
|
||||
add_weak_mods(MOD_BIT(kc));
|
||||
send_keyboard_report();
|
||||
}
|
||||
|
||||
static inline void qk_unregister_weak_mods(uint8_t kc) {
|
||||
del_weak_mods(MOD_BIT(kc));
|
||||
send_keyboard_report();
|
||||
}
|
||||
|
||||
static inline void qk_register_mods(uint8_t kc) {
|
||||
add_weak_mods(MOD_BIT(kc));
|
||||
send_keyboard_report();
|
||||
}
|
||||
|
||||
static inline void qk_unregister_mods(uint8_t kc) {
|
||||
del_weak_mods(MOD_BIT(kc));
|
||||
send_keyboard_report();
|
||||
f(mods_to_send);
|
||||
}
|
||||
|
||||
void register_code16(uint16_t code) {
|
||||
if (IS_MOD(code) || code == KC_NO) {
|
||||
do_code16(code, qk_register_mods);
|
||||
do_code16(code, register_mods);
|
||||
} else {
|
||||
do_code16(code, qk_register_weak_mods);
|
||||
do_code16(code, register_weak_mods);
|
||||
}
|
||||
register_code(code);
|
||||
}
|
||||
@@ -134,9 +124,9 @@ void register_code16(uint16_t code) {
|
||||
void unregister_code16(uint16_t code) {
|
||||
unregister_code(code);
|
||||
if (IS_MOD(code) || code == KC_NO) {
|
||||
do_code16(code, qk_unregister_mods);
|
||||
do_code16(code, unregister_mods);
|
||||
} else {
|
||||
do_code16(code, qk_unregister_weak_mods);
|
||||
do_code16(code, unregister_weak_mods);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,6 +571,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
keymap_config.swap_backslash_backspace = true;
|
||||
break;
|
||||
case MAGIC_HOST_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = true;
|
||||
break;
|
||||
case MAGIC_SWAP_ALT_GUI:
|
||||
@@ -623,6 +614,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
keymap_config.swap_backslash_backspace = false;
|
||||
break;
|
||||
case MAGIC_UNHOST_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_ALT_GUI:
|
||||
@@ -660,6 +652,7 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_TOGGLE_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = !keymap_config.nkro;
|
||||
break;
|
||||
default:
|
||||
@@ -723,6 +716,13 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef WEBUSB_ENABLE
|
||||
case WEBUSB_PAIR:
|
||||
if (record->event.pressed) {
|
||||
webusb_state.pairing = true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -967,6 +967,10 @@ void matrix_init_quantum() {
|
||||
#ifdef OUTPUT_AUTO_ENABLE
|
||||
set_output(OUTPUT_AUTO);
|
||||
#endif
|
||||
#ifdef DIP_SWITCH_ENABLE
|
||||
dip_switch_init();
|
||||
#endif
|
||||
|
||||
matrix_init_kb();
|
||||
}
|
||||
|
||||
@@ -1003,6 +1007,10 @@ void matrix_scan_quantum() {
|
||||
haptic_task();
|
||||
#endif
|
||||
|
||||
#ifdef DIP_SWITCH_ENABLE
|
||||
dip_switch_read(false);
|
||||
#endif
|
||||
|
||||
matrix_scan_kb();
|
||||
}
|
||||
#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
|
||||
@@ -1096,6 +1104,22 @@ void matrix_scan_quantum() {
|
||||
# define COMxx1 COM1A1
|
||||
# define OCRxx OCR1A
|
||||
# endif
|
||||
# elif defined(__AVR_ATmega328P__) && (BACKLIGHT_PIN == B1 || BACKLIGHT_PIN == B2)
|
||||
# define HARDWARE_PWM
|
||||
# define ICRx ICR1
|
||||
# define TCCRxA TCCR1A
|
||||
# define TCCRxB TCCR1B
|
||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||
# define TIMSKx TIMSK1
|
||||
# define TOIEx TOIE1
|
||||
|
||||
# if BACKLIGHT_PIN == B1
|
||||
# define COMxx1 COM1A1
|
||||
# define OCRxx OCR1A
|
||||
# elif BACKLIGHT_PIN == B2
|
||||
# define COMxx1 COM1B1
|
||||
# define OCRxx OCR1B
|
||||
# endif
|
||||
# else
|
||||
# if !defined(BACKLIGHT_CUSTOM_DRIVER)
|
||||
# if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
|
||||
|
||||
@@ -145,6 +145,11 @@ extern layer_state_t layer_state;
|
||||
# include "oled_driver.h"
|
||||
#endif
|
||||
|
||||
#ifdef DIP_SWITCH_ENABLE
|
||||
#include "dip_switch.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Function substitutions to ease GPIO manipulation
|
||||
#if defined(__AVR__)
|
||||
typedef uint8_t pin_t;
|
||||
|
||||
@@ -473,6 +473,9 @@ enum quantum_keycodes {
|
||||
HPT_BUZ,
|
||||
HPT_MODI,
|
||||
HPT_MODD,
|
||||
HPT_CONT,
|
||||
HPT_CONI,
|
||||
HPT_COND,
|
||||
HPT_DWLI,
|
||||
HPT_DWLD,
|
||||
|
||||
@@ -500,6 +503,8 @@ enum quantum_keycodes {
|
||||
MAGIC_UNSWAP_CTL_GUI,
|
||||
MAGIC_TOGGLE_CTL_GUI,
|
||||
|
||||
WEBUSB_PAIR,
|
||||
|
||||
// always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
||||
@@ -97,19 +97,33 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||
|
||||
#elif defined(WS2812)
|
||||
|
||||
extern LED_TYPE led[DRIVER_LED_TOTAL];
|
||||
// LED color buffer
|
||||
LED_TYPE led[DRIVER_LED_TOTAL];
|
||||
|
||||
static void init(void) {}
|
||||
|
||||
static void flush(void) {
|
||||
// Assumes use of RGB_DI_PIN
|
||||
ws2812_setleds(led, DRIVER_LED_TOTAL);
|
||||
}
|
||||
|
||||
static void init(void) {}
|
||||
// Set an led in the buffer to a color
|
||||
static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
led[i].r = r;
|
||||
led[i].g = g;
|
||||
led[i].b = b;
|
||||
}
|
||||
|
||||
static void setled_all(uint8_t r, uint8_t g, uint8_t b) {
|
||||
for (int i = 0; i < sizeof(led) / sizeof(led[0]); i++) {
|
||||
setled(i, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||
.init = init,
|
||||
.flush = flush,
|
||||
.set_color = ws2812_setled,
|
||||
.set_color_all = ws2812_setled_all,
|
||||
.set_color = setled,
|
||||
.set_color_all = setled_all,
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -910,6 +910,9 @@ void rgblight_effect_snake(animation_status_t *anim) {
|
||||
ledp->b = 0;
|
||||
for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
|
||||
k = pos + j * increment;
|
||||
if (k > RGBLED_NUM) {
|
||||
k = k % RGBLED_NUM;
|
||||
}
|
||||
if (k < 0) {
|
||||
k = k + effect_num_leds;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@ EXTRAKEY_ENABLE = yes
|
||||
CONSOLE_ENABLE = yes
|
||||
COMMAND_ENABLE = yes
|
||||
BACKLIGHT_ENABLE = no
|
||||
RGBLIGHT_ENABLE = no
|
||||
RGBLIGHT_CUSTOM_DRIVER = yes
|
||||
RGBLIGHT_ENABLE = yes
|
||||
WS2812_DRIVER = i2c
|
||||
|
||||
OPT_DEFS = -DDEBUG_LEVEL=0
|
||||
|
||||
SRC += i2c_master.c
|
||||
|
||||
@@ -15,44 +15,30 @@
|
||||
*/
|
||||
#include "%KEYBOARD%.h"
|
||||
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
|
||||
# include <string.h>
|
||||
# include "i2c_master.h"
|
||||
# include "rgblight.h"
|
||||
// Optional override functions below.
|
||||
// You can leave any or all of these undefined.
|
||||
// These are only required if you want to perform custom actions.
|
||||
|
||||
extern rgblight_config_t rgblight_config;
|
||||
/*
|
||||
|
||||
void matrix_init_kb(void) {
|
||||
i2c_init();
|
||||
// call user level keymaps, if any
|
||||
matrix_init_user();
|
||||
// put your keyboard start-up code here
|
||||
// runs once when the firmware starts up
|
||||
|
||||
matrix_init_user();
|
||||
}
|
||||
|
||||
// custom RGB driver
|
||||
void rgblight_set(void) {
|
||||
if (!rgblight_config.enable) {
|
||||
memset(led, 0, 3 * RGBLED_NUM);
|
||||
}
|
||||
|
||||
i2c_transmit(0xb0, (uint8_t*)led, 3 * RGBLED_NUM, 100);
|
||||
}
|
||||
|
||||
bool rgb_init = false;
|
||||
|
||||
void matrix_scan_kb(void) {
|
||||
// if LEDs were previously on before poweroff, turn them back on
|
||||
if (rgb_init == false && rgblight_config.enable) {
|
||||
i2c_transmit(0xb0, (uint8_t*)led, 3 * RGBLED_NUM, 100);
|
||||
rgb_init = true;
|
||||
}
|
||||
// put your looping keyboard code here
|
||||
// runs every cycle (a lot)
|
||||
|
||||
rgblight_task();
|
||||
matrix_scan_user();
|
||||
matrix_scan_user();
|
||||
}
|
||||
|
||||
#endif
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
// put your per-action keyboard code here
|
||||
// runs for every action, just before processing by the firmware
|
||||
|
||||
__attribute__ ((weak))
|
||||
void matrix_scan_user(void) {
|
||||
return process_record_user(keycode, record);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Python requirements
|
||||
# milc FIXME(skullydazed): Included in the repo for now.
|
||||
appdirs
|
||||
argcomplete
|
||||
colorama
|
||||
#halo
|
||||
|
||||
@@ -32,7 +32,7 @@ in
|
||||
stdenv.mkDerivation {
|
||||
name = "qmk-firmware";
|
||||
|
||||
buildInputs = [ dfu-programmer dfu-util diffutils git ]
|
||||
buildInputs = [ dfu-programmer dfu-util diffutils git python3 ]
|
||||
++ lib.optional avr [ avrbinutils avrgcc avrlibc avrdude ]
|
||||
++ lib.optional arm [ gcc-arm-embedded ]
|
||||
++ lib.optional teensy [ teensy-loader-cli ];
|
||||
|
||||
@@ -31,7 +31,8 @@ HARDWARE_OPTION_NAMES = \
|
||||
LED_BREATHING_TABLE \
|
||||
LED_TABLES \
|
||||
POINTING_DEVICE_ENABLE \
|
||||
VISUALIZER_ENABLE
|
||||
VISUALIZER_ENABLE \
|
||||
DIP_SWITCH_ENABLE
|
||||
|
||||
OTHER_OPTION_NAMES = \
|
||||
UNICODE_ENABLE \
|
||||
|
||||
@@ -147,7 +147,7 @@ define EXEC_DFU
|
||||
echo "Flashing '$(1)' for EE_HANDS split keyboard support." ;\
|
||||
fi; \
|
||||
until $(DFU_PROGRAMMER) $(MCU) get bootloader-version; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\
|
||||
sleep 5 ;\
|
||||
done; \
|
||||
if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\
|
||||
@@ -252,7 +252,7 @@ define EXEC_BOOTLOADHID
|
||||
# bootloadHid executable has no cross platform detect methods
|
||||
# so keep running bootloadHid if the output contains "The specified device was not found"
|
||||
until $(BOOTLOADHID_PROGRAMMER) -r $(BUILD_DIR)/$(TARGET).hex 2>&1 | tee /dev/stderr | grep -v "device was not found"; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\
|
||||
sleep 5 ;\
|
||||
done
|
||||
endef
|
||||
|
||||
@@ -236,7 +236,7 @@ qmk: $(BUILD_DIR)/$(TARGET).bin
|
||||
|
||||
define EXEC_DFU_UTIL
|
||||
until $(DFU_UTIL) -l | grep -q "Found DFU"; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\
|
||||
sleep 5 ;\
|
||||
done
|
||||
$(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin
|
||||
|
||||
@@ -118,6 +118,10 @@ ifeq ($(strip $(RAW_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DRAW_ENABLE
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(WEBUSB_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DWEBUSB_ENABLE
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CONSOLE_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DCONSOLE_ENABLE
|
||||
else
|
||||
@@ -153,11 +157,6 @@ ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes)
|
||||
TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
|
||||
TMK_COMMON_SRC += $(COMMON_DIR)/backlight.c
|
||||
TMK_COMMON_DEFS += -DBACKLIGHT_ENABLE
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
|
||||
TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
|
||||
|
||||
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "mousekey.h"
|
||||
#include "command.h"
|
||||
#include "led.h"
|
||||
#include "backlight.h"
|
||||
#include "action_layer.h"
|
||||
#include "action_tapping.h"
|
||||
#include "action_macro.h"
|
||||
@@ -28,6 +27,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "action.h"
|
||||
#include "wait.h"
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ACTION
|
||||
# include "debug.h"
|
||||
#else
|
||||
@@ -868,9 +871,9 @@ void tap_code(uint8_t code) {
|
||||
unregister_code(code);
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
* \param mods A bitfield of modifiers to unregister.
|
||||
*/
|
||||
void register_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
@@ -879,9 +882,9 @@ void register_mods(uint8_t mods) {
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
/** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately.
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
* \param mods A bitfield of modifiers to unregister.
|
||||
*/
|
||||
void unregister_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
@@ -890,6 +893,28 @@ void unregister_mods(uint8_t mods) {
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Adds the given weak modifiers and sends a keyboard report immediately.
|
||||
*
|
||||
* \param mods A bitfield of modifiers to register.
|
||||
*/
|
||||
void register_weak_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
add_weak_mods(mods);
|
||||
send_keyboard_report();
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Removes the given weak modifiers and sends a keyboard report immediately.
|
||||
*
|
||||
* \param mods A bitfield of modifiers to unregister.
|
||||
*/
|
||||
void unregister_weak_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
del_weak_mods(mods);
|
||||
send_keyboard_report();
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
|
||||
@@ -90,6 +90,8 @@ void unregister_code(uint8_t code);
|
||||
void tap_code(uint8_t code);
|
||||
void register_mods(uint8_t mods);
|
||||
void unregister_mods(uint8_t mods);
|
||||
void register_weak_mods(uint8_t mods);
|
||||
void unregister_weak_mods(uint8_t mods);
|
||||
// void set_mods(uint8_t mods);
|
||||
void clear_keyboard(void);
|
||||
void clear_keyboard_but_mods(void);
|
||||
|
||||
@@ -59,11 +59,6 @@
|
||||
uint16_t bootloader_start;
|
||||
#endif
|
||||
|
||||
#define BOOT_SIZE_256 0b110
|
||||
#define BOOT_SIZE_512 0b100
|
||||
#define BOOT_SIZE_1024 0b010
|
||||
#define BOOT_SIZE_2048 0b000
|
||||
|
||||
// compatibility between ATMega8 and ATMega88
|
||||
#if !defined(MCUCSR)
|
||||
# if defined(MCUSR)
|
||||
@@ -86,11 +81,11 @@ void bootloader_jump(void) {
|
||||
#if !defined(BOOTLOADER_SIZE)
|
||||
uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
|
||||
|
||||
if (high_fuse & BOOT_SIZE_256) {
|
||||
if (high_fuse & ~(FUSE_BOOTSZ0 & FUSE_BOOTSZ1)) {
|
||||
bootloader_start = (FLASH_SIZE - 512) >> 1;
|
||||
} else if (high_fuse & BOOT_SIZE_512) {
|
||||
} else if (high_fuse & ~(FUSE_BOOTSZ1)) {
|
||||
bootloader_start = (FLASH_SIZE - 1024) >> 1;
|
||||
} else if (high_fuse & BOOT_SIZE_1024) {
|
||||
} else if (high_fuse & ~(FUSE_BOOTSZ0)) {
|
||||
bootloader_start = (FLASH_SIZE - 2048) >> 1;
|
||||
} else {
|
||||
bootloader_start = (FLASH_SIZE - 4096) >> 1;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include "matrix.h"
|
||||
#include "action.h"
|
||||
#include "backlight.h"
|
||||
#include "suspend_avr.h"
|
||||
#include "suspend.h"
|
||||
#include "timer.h"
|
||||
@@ -16,6 +15,10 @@
|
||||
# include "lufa.h"
|
||||
#endif
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
# include "audio.h"
|
||||
#endif /* AUDIO_ENABLE */
|
||||
|
||||
@@ -32,33 +32,32 @@ volatile uint32_t timer_count;
|
||||
*/
|
||||
void timer_init(void) {
|
||||
#if TIMER_PRESCALER == 1
|
||||
uint8_t prescaler = 0x01;
|
||||
uint8_t prescaler = _BV(CS00);
|
||||
#elif TIMER_PRESCALER == 8
|
||||
uint8_t prescaler = 0x02;
|
||||
uint8_t prescaler = _BV(CS01);
|
||||
#elif TIMER_PRESCALER == 64
|
||||
uint8_t prescaler = 0x03;
|
||||
uint8_t prescaler = _BV(CS00) | _BV(CS01);
|
||||
#elif TIMER_PRESCALER == 256
|
||||
uint8_t prescaler = 0x04;
|
||||
uint8_t prescaler = _BV(CS02);
|
||||
#elif TIMER_PRESCALER == 1024
|
||||
uint8_t prescaler = 0x05;
|
||||
uint8_t prescaler = _BV(CS00) | _BV(CS02);
|
||||
#else
|
||||
# error "Timer prescaler value is NOT vaild."
|
||||
# error "Timer prescaler value is not valid"
|
||||
#endif
|
||||
|
||||
#ifndef __AVR_ATmega32A__
|
||||
// Timer0 CTC mode
|
||||
TCCR0A = 0x02;
|
||||
|
||||
TCCR0A = _BV(WGM01);
|
||||
TCCR0B = prescaler;
|
||||
|
||||
OCR0A = TIMER_RAW_TOP;
|
||||
TIMSK0 = (1 << OCIE0A);
|
||||
TIMSK0 = _BV(OCIE0A);
|
||||
#else
|
||||
// Timer0 CTC mode
|
||||
TCCR0 = (1 << WGM01) | prescaler;
|
||||
TCCR0 = _BV(WGM01) | prescaler;
|
||||
|
||||
OCR0 = TIMER_RAW_TOP;
|
||||
TIMSK = (1 << OCIE0);
|
||||
TIMSK = _BV(OCIE0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user