Compare commits
47 Commits
reviung34
...
refactor-p
Author | SHA1 | Date | |
---|---|---|---|
|
cbfcd34fae | ||
|
1d53d3a8da | ||
|
0e804ffd54 | ||
|
0cc308c055 | ||
|
c575fa396a | ||
|
a83e833d10 | ||
|
e9af3e542a | ||
|
16d319359f | ||
|
88c3616b6a | ||
|
6ab4154ad5 | ||
|
db2082f1c6 | ||
|
317f6407d6 | ||
|
08c255b6e4 | ||
|
61cf527370 | ||
|
38acda77b4 | ||
|
7ef2c2c2d3 | ||
|
1f751d8374 | ||
|
d4fe745e71 | ||
|
1674ff4ed7 | ||
|
a90d569690 | ||
|
449aab7dcb | ||
|
dc9b5f4512 | ||
|
cbaddef9a6 | ||
|
804b5ec575 | ||
|
a28df47199 | ||
|
9e5d2c24e1 | ||
|
ca800331de | ||
|
1ca27dab58 | ||
|
fc8d5edd52 | ||
|
e84bbd0d75 | ||
|
69d47343e8 | ||
|
470f16c97f | ||
|
27f101d139 | ||
|
2852420ea8 | ||
|
5a38af6632 | ||
|
fa7d72b175 | ||
|
d7e9cfbc5b | ||
|
408f2f487e | ||
|
5af52addf8 | ||
|
705d3eb032 | ||
|
638d64af72 | ||
|
e7427ff53b | ||
|
62d6bf16df | ||
|
47c242a2c9 | ||
|
4d52afa086 | ||
|
1935f05ccb | ||
|
83110c5f80 |
103
Makefile
103
Makefile
@@ -30,19 +30,19 @@ TIMESTAMP := $(shell date +%s)
|
|||||||
|
|
||||||
all: copy-kmk copy-bootpy copy-keymap copy-board
|
all: copy-kmk copy-bootpy copy-keymap copy-board
|
||||||
|
|
||||||
compile: $(MPY_TARGET_DIR)/.mpy.compiled
|
.PHONY: compile compile-check
|
||||||
|
compile: compile-check
|
||||||
$(MPY_TARGET_DIR)/.mpy.compiled: $(PY_KMK_TREE)
|
|
||||||
ifeq ($(MPY_CROSS),)
|
ifeq ($(MPY_CROSS),)
|
||||||
|
compile-check:
|
||||||
@echo "===> Could not find mpy-cross in PATH, exiting"
|
@echo "===> Could not find mpy-cross in PATH, exiting"
|
||||||
@false
|
@false
|
||||||
endif
|
else
|
||||||
|
compile-check: $(PY_KMK_TREE:%.py=$(MPY_TARGET_DIR)/%.mpy)
|
||||||
@echo "===> Compiling all py files to mpy with flags $(MPY_FLAGS)"
|
@echo "===> Compiling all py files to mpy with flags $(MPY_FLAGS)"
|
||||||
@mkdir -p $(MPY_TARGET_DIR)
|
$(MPY_TARGET_DIR)/%.mpy: %.py
|
||||||
@echo "KMK_RELEASE = '$(DIST_DESCRIBE)'" > $(MPY_SOURCES)/release_info.py
|
@mkdir -p $(dir $@)
|
||||||
@find $(MPY_SOURCES) -name "*.py" -exec sh -c 'mkdir -p $(MPY_TARGET_DIR)/$$(dirname {}) && $(MPY_CROSS) $(MPY_FLAGS) {} -o $(MPY_TARGET_DIR)/$$(dirname {})/$$(basename -s .py {}).mpy' \;
|
@$(MPY_CROSS) $(MPY_FLAGS) $? -o $@
|
||||||
@rm -rf $(MPY_SOURCES)/release_info.py
|
endif
|
||||||
@touch $(MPY_TARGET_DIR)/.mpy.compiled
|
|
||||||
|
|
||||||
.devdeps: Pipfile.lock
|
.devdeps: Pipfile.lock
|
||||||
@echo "===> Installing dependencies with pipenv"
|
@echo "===> Installing dependencies with pipenv"
|
||||||
@@ -92,7 +92,7 @@ test: lint unit-tests
|
|||||||
|
|
||||||
.PHONY: unit-tests
|
.PHONY: unit-tests
|
||||||
unit-tests: devdeps
|
unit-tests: devdeps
|
||||||
@$(PIPENV) run python3 -m unittest
|
@$(PIPENV) run python3 -m unittest $(TESTS)
|
||||||
|
|
||||||
reset-bootloader:
|
reset-bootloader:
|
||||||
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
|
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
|
||||||
@@ -102,55 +102,44 @@ reset-board:
|
|||||||
@echo "===> Rebooting your board (safe to ignore file not found errors)"
|
@echo "===> Rebooting your board (safe to ignore file not found errors)"
|
||||||
@-timeout -k 5s 10s $(PIPENV) run ampy -p /dev/ttyACM0 -d ${AMPY_DELAY} -b ${AMPY_BAUD} run util/reset.py
|
@-timeout -k 5s 10s $(PIPENV) run ampy -p /dev/ttyACM0 -d ${AMPY_DELAY} -b ${AMPY_BAUD} run util/reset.py
|
||||||
|
|
||||||
ifdef MOUNTPOINT
|
|
||||||
$(MOUNTPOINT)/kmk/.copied: $(shell find kmk/ -name "*.py" | xargs -0)
|
|
||||||
@echo "===> Copying KMK source folder"
|
|
||||||
@rsync -rh kmk $(MOUNTPOINT)/
|
|
||||||
@touch $(MOUNTPOINT)/kmk/.copied
|
|
||||||
@sync
|
|
||||||
|
|
||||||
copy-kmk: $(MOUNTPOINT)/kmk/.copied
|
|
||||||
else
|
|
||||||
copy-kmk:
|
|
||||||
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
copy-board: $(MOUNTPOINT)/kb.py
|
|
||||||
$(MOUNTPOINT)/kb.py: $(BOARD)
|
|
||||||
@echo "===> Copying your board to kb.py"
|
|
||||||
@rsync -rh $(BOARD) $@
|
|
||||||
@sync
|
|
||||||
|
|
||||||
ifdef MOUNTPOINT
|
ifdef MOUNTPOINT
|
||||||
$(MOUNTPOINT)/kmk/boot.py: boot.py
|
|
||||||
@echo "===> Copying required boot.py"
|
|
||||||
@rsync -rh boot.py $(MOUNTPOINT)/
|
|
||||||
@sync
|
|
||||||
|
|
||||||
copy-bootpy: $(MOUNTPOINT)/kmk/boot.py
|
|
||||||
else
|
|
||||||
copy-bootpy:
|
|
||||||
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef MOUNTPOINT
|
|
||||||
ifndef USER_KEYMAP
|
|
||||||
$(MOUNTPOINT)/main.py:
|
|
||||||
@echo "**** USER_KEYMAP must be defined (ex. USER_KEYMAP=user_keymaps/noop.py) ****" && exit 1
|
|
||||||
else
|
|
||||||
$(MOUNTPOINT)/main.py: $(USER_KEYMAP)
|
|
||||||
@echo "===> Copying your keymap to main.py"
|
|
||||||
@rsync -rh $(USER_KEYMAP) $@
|
|
||||||
@sync
|
|
||||||
endif # USER_KEYMAP
|
|
||||||
|
|
||||||
copy-keymap: $(MOUNTPOINT)/main.py
|
|
||||||
else
|
|
||||||
copy-keymap:
|
|
||||||
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
|
|
||||||
|
|
||||||
ifdef BOARD
|
ifdef BOARD
|
||||||
copy-board: $(MOUNTPOINT)/kb.py
|
copy-board:
|
||||||
|
@echo "===> Copying your board from $(BOARD) to $(MOUNTPOINT)"
|
||||||
|
@rsync -rhu $(BOARD)/*.py $(MOUNTPOINT)/
|
||||||
|
@sync
|
||||||
|
else # BOARD
|
||||||
|
copy-board:
|
||||||
|
@echo "**** Missing BOARD argument ****" && exit 1
|
||||||
endif # BOARD
|
endif # BOARD
|
||||||
|
|
||||||
endif # MOUNTPOINT
|
copy-bootpy:
|
||||||
|
@echo "===> Copying required boot.py"
|
||||||
|
@rsync -rhu boot.py $(MOUNTPOINT)/boot.py
|
||||||
|
@sync
|
||||||
|
|
||||||
|
copy-compiled:
|
||||||
|
@echo "===> Copying compiled KMK folder"
|
||||||
|
@rsync -rhu $(MPY_TARGET_DIR)/* $(MOUNTPOINT)/
|
||||||
|
@sync
|
||||||
|
|
||||||
|
ifdef USER_KEYMAP
|
||||||
|
copy-keymap:
|
||||||
|
@echo "===> Copying your keymap to main.py"
|
||||||
|
@rsync -rhu $(USER_KEYMAP) $(MOUNTPOINT)/main.py
|
||||||
|
@sync
|
||||||
|
else # USER_KEYMAP
|
||||||
|
copy-keymap:
|
||||||
|
@echo "**** Missing USER_KEYMAP argument ****" && exit 1
|
||||||
|
endif # USER_KEYMAP
|
||||||
|
|
||||||
|
copy-kmk:
|
||||||
|
@echo "===> Copying KMK source folder"
|
||||||
|
@rsync -rhu kmk $(MOUNTPOINT)/
|
||||||
|
@sync
|
||||||
|
|
||||||
|
else # MOUNTPOINT
|
||||||
|
copy-board copy-bootpy copy-compiled copy-keymap copy-kmk:
|
||||||
|
@echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
|
||||||
|
endif # ifndef MOUNTPOINT
|
||||||
|
2
Pipfile
2
Pipfile
@@ -17,6 +17,6 @@ ipython = "*"
|
|||||||
isort = "*"
|
isort = "*"
|
||||||
neovim = "*"
|
neovim = "*"
|
||||||
s3cmd = "*"
|
s3cmd = "*"
|
||||||
black = "==21.6b0"
|
black = "==22.3.0"
|
||||||
flake8-quotes = "*"
|
flake8-quotes = "*"
|
||||||
flake8-black = "*"
|
flake8-black = "*"
|
||||||
|
426
Pipfile.lock
generated
426
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "0a04ec24d4aef6828e4f5eefa0a7d2c312f21f2b2f18c42c7004cdbe0c02bd53"
|
"sha256": "8c1b0ad909dc0ac0fc8013756ca7db8b5420f51c25cc1c2d1612f62fe5e19843"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {},
|
"requires": {},
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==1.1.0"
|
"version": "==1.1.0"
|
||||||
},
|
},
|
||||||
"appdirs": {
|
"asttokens": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
|
"sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3",
|
||||||
"sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
|
"sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"
|
||||||
],
|
],
|
||||||
"version": "==1.4.4"
|
"version": "==2.2.1"
|
||||||
},
|
},
|
||||||
"backcall": {
|
"backcall": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -39,11 +39,32 @@
|
|||||||
},
|
},
|
||||||
"black": {
|
"black": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04",
|
"sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b",
|
||||||
"sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"
|
"sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176",
|
||||||
|
"sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09",
|
||||||
|
"sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a",
|
||||||
|
"sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015",
|
||||||
|
"sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79",
|
||||||
|
"sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb",
|
||||||
|
"sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20",
|
||||||
|
"sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464",
|
||||||
|
"sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968",
|
||||||
|
"sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82",
|
||||||
|
"sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21",
|
||||||
|
"sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0",
|
||||||
|
"sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265",
|
||||||
|
"sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b",
|
||||||
|
"sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a",
|
||||||
|
"sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72",
|
||||||
|
"sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce",
|
||||||
|
"sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0",
|
||||||
|
"sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a",
|
||||||
|
"sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163",
|
||||||
|
"sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad",
|
||||||
|
"sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==21.6b0"
|
"version": "==22.3.0"
|
||||||
},
|
},
|
||||||
"click": {
|
"click": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -58,144 +79,152 @@
|
|||||||
"sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330",
|
"sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330",
|
||||||
"sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"
|
"sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.5'",
|
"markers": "python_version < '3.11' and python_version >= '3.7'",
|
||||||
"version": "==5.1.1"
|
"version": "==5.1.1"
|
||||||
},
|
},
|
||||||
|
"executing": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc",
|
||||||
|
"sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"
|
||||||
|
],
|
||||||
|
"version": "==1.2.0"
|
||||||
|
},
|
||||||
"flake8": {
|
"flake8": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b",
|
"sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7",
|
||||||
"sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"
|
"sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==3.9.2"
|
"version": "==6.0.0"
|
||||||
},
|
},
|
||||||
"flake8-black": {
|
"flake8-black": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:941514149cb8b489cb17a4bb1cf18d84375db3b34381bb018de83509437931a0",
|
"sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34",
|
||||||
"sha256:f26651bc10db786c03f4093414f7c9ea982ed8a244cec323c984feeffdf4c118"
|
"sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.2.1"
|
"version": "==0.3.6"
|
||||||
},
|
},
|
||||||
"flake8-commas": {
|
"flake8-commas": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d3005899466f51380387df7151fb59afec666a0f4f4a2c6a8995b975de0f44b7",
|
"sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263",
|
||||||
"sha256:ee2141a3495ef9789a3894ed8802d03eff1eaaf98ce6d8653a7c573ef101935e"
|
"sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.0.0"
|
"version": "==2.1.0"
|
||||||
},
|
},
|
||||||
"flake8-comprehensions": {
|
"flake8-comprehensions": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:b07aef3277623db32310aa241a1cec67212b53c1d18e767d7e26d4d83aa05bf7",
|
"sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab",
|
||||||
"sha256:f24be9032587127f7a5bc6d066bf755b6e66834f694383adb8a673e229c1f559"
|
"sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==3.5.0"
|
"version": "==3.10.1"
|
||||||
},
|
},
|
||||||
"flake8-isort": {
|
"flake8-isort": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:2b91300f4f1926b396c2c90185844eb1a3d5ec39ea6138832d119da0a208f4d9",
|
"sha256:537f453a660d7e903f602ecfa36136b140de279df58d02eb1b6a0c84e83c528c",
|
||||||
"sha256:729cd6ef9ba3659512dee337687c05d79c78e1215fdf921ed67e5fe46cce2f3c"
|
"sha256:aa0cac02a62c7739e370ce6b9c31743edac904bae4b157274511fc8a19c75bbc"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==4.0.0"
|
"version": "==6.0.0"
|
||||||
},
|
},
|
||||||
"flake8-quotes": {
|
"flake8-quotes": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:3f1116e985ef437c130431ac92f9b3155f8f652fda7405ac22ffdfd7a9d1055e"
|
"sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==3.2.0"
|
"version": "==3.3.2"
|
||||||
},
|
},
|
||||||
"greenlet": {
|
"greenlet": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9",
|
"sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a",
|
||||||
"sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9",
|
"sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a",
|
||||||
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581",
|
"sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43",
|
||||||
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26",
|
"sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33",
|
||||||
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd",
|
"sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8",
|
||||||
"sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2",
|
"sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088",
|
||||||
"sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a",
|
"sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca",
|
||||||
"sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82",
|
"sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343",
|
||||||
"sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a",
|
"sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645",
|
||||||
"sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce",
|
"sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db",
|
||||||
"sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f",
|
"sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df",
|
||||||
"sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524",
|
"sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3",
|
||||||
"sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48",
|
"sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86",
|
||||||
"sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77",
|
"sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2",
|
||||||
"sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928",
|
"sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a",
|
||||||
"sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e",
|
"sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf",
|
||||||
"sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67",
|
"sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7",
|
||||||
"sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9",
|
"sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394",
|
||||||
"sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68",
|
"sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40",
|
||||||
"sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd",
|
"sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3",
|
||||||
"sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515",
|
"sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6",
|
||||||
"sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5",
|
"sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74",
|
||||||
"sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39",
|
"sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0",
|
||||||
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94",
|
"sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3",
|
||||||
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92",
|
"sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91",
|
||||||
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e",
|
"sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5",
|
||||||
"sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726",
|
"sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9",
|
||||||
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd",
|
"sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8",
|
||||||
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5",
|
"sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b",
|
||||||
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764",
|
"sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6",
|
||||||
"sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955",
|
"sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb",
|
||||||
"sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608",
|
"sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73",
|
||||||
"sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148",
|
"sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b",
|
||||||
"sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51",
|
"sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df",
|
||||||
"sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9",
|
"sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9",
|
||||||
"sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d",
|
"sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f",
|
||||||
"sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c",
|
"sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0",
|
||||||
"sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72",
|
"sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857",
|
||||||
"sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1",
|
"sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a",
|
||||||
"sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2",
|
"sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249",
|
||||||
"sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23",
|
"sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30",
|
||||||
"sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb",
|
"sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292",
|
||||||
"sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6",
|
"sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b",
|
||||||
"sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19",
|
"sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d",
|
||||||
"sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45",
|
"sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b",
|
||||||
"sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000",
|
"sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c",
|
||||||
"sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da",
|
"sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca",
|
||||||
"sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617",
|
"sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7",
|
||||||
"sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963",
|
"sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75",
|
||||||
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7",
|
"sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae",
|
||||||
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d",
|
"sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b",
|
||||||
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d",
|
"sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470",
|
||||||
"sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0",
|
"sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564",
|
||||||
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243",
|
"sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9",
|
||||||
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce",
|
"sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099",
|
||||||
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6",
|
"sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0",
|
||||||
"sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a",
|
"sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5",
|
||||||
"sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1",
|
"sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19",
|
||||||
"sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f",
|
"sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1",
|
||||||
"sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"
|
"sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||||
"version": "==2.0.1"
|
"version": "==2.0.2"
|
||||||
},
|
},
|
||||||
"ipdb": {
|
"ipdb": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"
|
"sha256:c23b6736f01fd4586cc2ecbebdf79a5eb454796853e1cd8f2ed3b7b91d4a3e93",
|
||||||
|
"sha256:f74c2f741c18b909eaf89f19fde973f745ac721744aa1465888ce45813b63a9c"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.13.9"
|
"version": "==0.13.11"
|
||||||
},
|
},
|
||||||
"ipython": {
|
"ipython": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:55df3e0bd0f94e715abd968bedd89d4e8a7bce4bf498fb123fed4f5398fea874",
|
"sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e",
|
||||||
"sha256:b5548ec5329a4bcf054a5deed5099b0f9622eb9ea51aaa7104d215fece201d8c"
|
"sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==7.31.1"
|
"version": "==8.10.0"
|
||||||
},
|
},
|
||||||
"isort": {
|
"isort": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6",
|
"sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504",
|
||||||
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"
|
"sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==5.8.0"
|
"version": "==5.12.0"
|
||||||
},
|
},
|
||||||
"jedi": {
|
"jedi": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -215,10 +244,11 @@
|
|||||||
},
|
},
|
||||||
"mccabe": {
|
"mccabe": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
|
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
|
||||||
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
|
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
|
||||||
],
|
],
|
||||||
"version": "==0.6.1"
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==0.7.0"
|
||||||
},
|
},
|
||||||
"msgpack": {
|
"msgpack": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -279,10 +309,11 @@
|
|||||||
},
|
},
|
||||||
"mypy-extensions": {
|
"mypy-extensions": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
|
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
|
||||||
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
|
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
|
||||||
],
|
],
|
||||||
"version": "==0.4.3"
|
"markers": "python_version >= '3.5'",
|
||||||
|
"version": "==1.0.0"
|
||||||
},
|
},
|
||||||
"neovim": {
|
"neovim": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -301,11 +332,11 @@
|
|||||||
},
|
},
|
||||||
"pathspec": {
|
"pathspec": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6",
|
"sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229",
|
||||||
"sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"
|
"sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==0.10.3"
|
"version": "==0.11.0"
|
||||||
},
|
},
|
||||||
"pexpect": {
|
"pexpect": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -322,6 +353,14 @@
|
|||||||
],
|
],
|
||||||
"version": "==0.7.5"
|
"version": "==0.7.5"
|
||||||
},
|
},
|
||||||
|
"platformdirs": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9",
|
||||||
|
"sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.7'",
|
||||||
|
"version": "==3.0.0"
|
||||||
|
},
|
||||||
"prompt-toolkit": {
|
"prompt-toolkit": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63",
|
"sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63",
|
||||||
@@ -337,29 +376,36 @@
|
|||||||
],
|
],
|
||||||
"version": "==0.7.0"
|
"version": "==0.7.0"
|
||||||
},
|
},
|
||||||
|
"pure-eval": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350",
|
||||||
|
"sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"
|
||||||
|
],
|
||||||
|
"version": "==0.2.2"
|
||||||
|
},
|
||||||
"pycodestyle": {
|
"pycodestyle": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068",
|
"sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
|
||||||
"sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"
|
"sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '3.6'",
|
||||||
"version": "==2.7.0"
|
"version": "==2.10.0"
|
||||||
},
|
},
|
||||||
"pyflakes": {
|
"pyflakes": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3",
|
"sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf",
|
||||||
"sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"
|
"sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '3.6'",
|
||||||
"version": "==2.3.1"
|
"version": "==3.0.1"
|
||||||
},
|
},
|
||||||
"pygments": {
|
"pygments": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1",
|
"sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297",
|
||||||
"sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"
|
"sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.6'",
|
"markers": "python_version >= '3.6'",
|
||||||
"version": "==2.13.0"
|
"version": "==2.14.0"
|
||||||
},
|
},
|
||||||
"pynvim": {
|
"pynvim": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -384,129 +430,27 @@
|
|||||||
},
|
},
|
||||||
"python-dotenv": {
|
"python-dotenv": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5",
|
"sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
|
||||||
"sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"
|
"sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==0.21.0"
|
"version": "==0.21.1"
|
||||||
},
|
},
|
||||||
"python-magic": {
|
"python-magic": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626",
|
"sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b",
|
||||||
"sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf"
|
"sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.4.24"
|
"version": "==0.4.27"
|
||||||
},
|
|
||||||
"regex": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad",
|
|
||||||
"sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4",
|
|
||||||
"sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd",
|
|
||||||
"sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc",
|
|
||||||
"sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d",
|
|
||||||
"sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066",
|
|
||||||
"sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec",
|
|
||||||
"sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9",
|
|
||||||
"sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e",
|
|
||||||
"sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8",
|
|
||||||
"sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e",
|
|
||||||
"sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783",
|
|
||||||
"sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6",
|
|
||||||
"sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1",
|
|
||||||
"sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c",
|
|
||||||
"sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4",
|
|
||||||
"sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1",
|
|
||||||
"sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1",
|
|
||||||
"sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7",
|
|
||||||
"sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8",
|
|
||||||
"sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe",
|
|
||||||
"sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d",
|
|
||||||
"sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b",
|
|
||||||
"sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8",
|
|
||||||
"sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c",
|
|
||||||
"sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af",
|
|
||||||
"sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49",
|
|
||||||
"sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714",
|
|
||||||
"sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542",
|
|
||||||
"sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318",
|
|
||||||
"sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e",
|
|
||||||
"sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5",
|
|
||||||
"sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc",
|
|
||||||
"sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144",
|
|
||||||
"sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453",
|
|
||||||
"sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5",
|
|
||||||
"sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61",
|
|
||||||
"sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11",
|
|
||||||
"sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a",
|
|
||||||
"sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54",
|
|
||||||
"sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73",
|
|
||||||
"sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc",
|
|
||||||
"sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347",
|
|
||||||
"sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c",
|
|
||||||
"sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66",
|
|
||||||
"sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c",
|
|
||||||
"sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93",
|
|
||||||
"sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443",
|
|
||||||
"sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc",
|
|
||||||
"sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1",
|
|
||||||
"sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892",
|
|
||||||
"sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8",
|
|
||||||
"sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001",
|
|
||||||
"sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa",
|
|
||||||
"sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90",
|
|
||||||
"sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c",
|
|
||||||
"sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0",
|
|
||||||
"sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692",
|
|
||||||
"sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4",
|
|
||||||
"sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5",
|
|
||||||
"sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690",
|
|
||||||
"sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83",
|
|
||||||
"sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66",
|
|
||||||
"sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f",
|
|
||||||
"sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f",
|
|
||||||
"sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4",
|
|
||||||
"sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee",
|
|
||||||
"sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81",
|
|
||||||
"sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95",
|
|
||||||
"sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9",
|
|
||||||
"sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff",
|
|
||||||
"sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e",
|
|
||||||
"sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5",
|
|
||||||
"sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6",
|
|
||||||
"sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7",
|
|
||||||
"sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1",
|
|
||||||
"sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394",
|
|
||||||
"sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6",
|
|
||||||
"sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742",
|
|
||||||
"sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57",
|
|
||||||
"sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b",
|
|
||||||
"sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7",
|
|
||||||
"sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b",
|
|
||||||
"sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244",
|
|
||||||
"sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af",
|
|
||||||
"sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185",
|
|
||||||
"sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8",
|
|
||||||
"sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"
|
|
||||||
],
|
|
||||||
"markers": "python_version >= '3.6'",
|
|
||||||
"version": "==2022.10.31"
|
|
||||||
},
|
},
|
||||||
"s3cmd": {
|
"s3cmd": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa",
|
"sha256:15330776e7ff993d8ae0ac213bf896f210719e9b91445f5f7626a8fa7e74e30b",
|
||||||
"sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03"
|
"sha256:2204306742c33c24fbca02b78e059bacfc1bfc04af09c7e9866f267a11a9ddb2"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.1.0"
|
"version": "==2.3.0"
|
||||||
},
|
|
||||||
"setuptools": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
|
|
||||||
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==65.5.1"
|
|
||||||
},
|
},
|
||||||
"six": {
|
"six": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -516,35 +460,35 @@
|
|||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==1.16.0"
|
"version": "==1.16.0"
|
||||||
},
|
},
|
||||||
"testfixtures": {
|
"stack-data": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:02dae883f567f5b70fd3ad3c9eefb95912e78ac90be6c7444b5e2f46bf572c84",
|
"sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815",
|
||||||
"sha256:7de200e24f50a4a5d6da7019fb1197aaf5abd475efb2ec2422fdcf2f2eb98c1d"
|
"sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"
|
||||||
],
|
],
|
||||||
"version": "==6.18.5"
|
"version": "==0.6.2"
|
||||||
},
|
},
|
||||||
"toml": {
|
"tomli": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
|
||||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version < '3.11'",
|
||||||
"version": "==0.10.2"
|
"version": "==2.0.1"
|
||||||
},
|
},
|
||||||
"traitlets": {
|
"traitlets": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:6cc57d6dc28c85d5365961726ffd19b538739347749e13ebe34e03323a0e8f84",
|
"sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8",
|
||||||
"sha256:c864831efa0ba6576d09b44884b34e41defc18c0d7e720b4a2d6698c842cab3e"
|
"sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==5.8.0"
|
"version": "==5.9.0"
|
||||||
},
|
},
|
||||||
"wcwidth": {
|
"wcwidth": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
|
"sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e",
|
||||||
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
|
"sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"
|
||||||
],
|
],
|
||||||
"version": "==0.2.5"
|
"version": "==0.2.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ knob.extensions.append(media_keys)
|
|||||||
|
|
||||||
# Rotary encoder that also acts as a key
|
# Rotary encoder that also acts as a key
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
|
encoder_handler.divisor = 2
|
||||||
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
|
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
|
||||||
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
||||||
knob.modules.append(encoder_handler)
|
knob.modules.append(encoder_handler)
|
||||||
|
@@ -15,6 +15,7 @@ knob.extensions.append(media_keys)
|
|||||||
|
|
||||||
# Rotary encoders that also acts as keys
|
# Rotary encoders that also acts as keys
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
|
encoder_handler.divisor = 2
|
||||||
encoder_handler.pins = (
|
encoder_handler.pins = (
|
||||||
(board.D1, board.D2, board.D0),
|
(board.D1, board.D2, board.D0),
|
||||||
(board.D9, board.D10, board.D3),
|
(board.D9, board.D10, board.D3),
|
||||||
|
@@ -78,6 +78,7 @@ keyboard.keymap = [
|
|||||||
|
|
||||||
# Rotary encoder that also acts as a key
|
# Rotary encoder that also acts as a key
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
|
encoder_handler.divisor = 2
|
||||||
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
|
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
|
||||||
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
||||||
keyboard.modules.append(encoder_handler)
|
keyboard.modules.append(encoder_handler)
|
||||||
|
12
boards/anavi/macro-pad-12/README.md
Normal file
12
boards/anavi/macro-pad-12/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# ANAVI Macro Pad 12
|
||||||
|
|
||||||
|
ANAVI Macro Pad 12 is an open source, programmable mechanical keyboard with 9 hot-swappable mechanical switches, RGB WS2812B underlighting and yellow backlit a rotary encoder and [Seeed XIAO RP2040](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html).
|
||||||
|
|
||||||
|
ANAVI Macro Pad 12 has been designed with the cross platform and open source electronics design automation suite KiCad. All KiCad [files and schematics are available at GitHub](https://github.com/anavitechnology/anavi-macro-pad-12) under [Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/).
|
||||||
|
|
||||||
|
Extensions enabled by default:
|
||||||
|
- [Encoder](/docs/en/encoder.md) Twist control for all the things
|
||||||
|
- [LED](/docs/en/led.md) Light your keys up (for backlit)
|
||||||
|
- [RGB](/docs/en/rgb.md) Light it up (for underlighting)
|
||||||
|
- [MediaKeys](/docs/en/media_keys.md) Control volume and other media functions
|
||||||
|
- [PEG_OLED](/docs/peg_oled_display.md) Show information on the mini OLED display
|
97
boards/anavi/macro-pad-12/code.py
Normal file
97
boards/anavi/macro-pad-12/code.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import board
|
||||||
|
|
||||||
|
from kmk.extensions.LED import LED
|
||||||
|
from kmk.extensions.media_keys import MediaKeys
|
||||||
|
from kmk.extensions.peg_oled_Display import (
|
||||||
|
Oled,
|
||||||
|
OledData,
|
||||||
|
OledDisplayMode,
|
||||||
|
OledReactionType,
|
||||||
|
)
|
||||||
|
from kmk.extensions.RGB import RGB, AnimationModes
|
||||||
|
from kmk.keys import KC
|
||||||
|
from kmk.kmk_keyboard import KMKKeyboard
|
||||||
|
from kmk.scanners import DiodeOrientation
|
||||||
|
|
||||||
|
keyboard = KMKKeyboard()
|
||||||
|
|
||||||
|
# I2C pins for the mini OLED display
|
||||||
|
keyboard.SCL = board.D5
|
||||||
|
keyboard.SDA = board.D4
|
||||||
|
|
||||||
|
oled_ext = Oled(
|
||||||
|
OledData(
|
||||||
|
corner_one={0: OledReactionType.STATIC, 1: ['ANAVI Macro Pad 12']},
|
||||||
|
corner_two={0: OledReactionType.STATIC, 1: [' ']},
|
||||||
|
corner_three={0: OledReactionType.STATIC, 1: ['Open Source']},
|
||||||
|
corner_four={0: OledReactionType.STATIC, 1: [' ']},
|
||||||
|
),
|
||||||
|
oWidth=128,
|
||||||
|
oHeight=64,
|
||||||
|
toDisplay=OledDisplayMode.TXT,
|
||||||
|
flip=False,
|
||||||
|
)
|
||||||
|
keyboard.extensions.append(oled_ext)
|
||||||
|
|
||||||
|
led_ext = LED(
|
||||||
|
led_pin=[
|
||||||
|
board.D0,
|
||||||
|
],
|
||||||
|
brightness=100,
|
||||||
|
brightness_step=5,
|
||||||
|
brightness_limit=100,
|
||||||
|
breathe_center=1.5,
|
||||||
|
animation_mode=AnimationModes.STATIC,
|
||||||
|
animation_speed=1,
|
||||||
|
user_animation=None,
|
||||||
|
val=100,
|
||||||
|
)
|
||||||
|
keyboard.extensions.append(led_ext)
|
||||||
|
|
||||||
|
# WS2812B LED strips on the back
|
||||||
|
underglow = RGB(
|
||||||
|
pixel_pin=board.D10,
|
||||||
|
num_pixels=6,
|
||||||
|
val_limit=100,
|
||||||
|
val_default=25,
|
||||||
|
animation_mode=AnimationModes.RAINBOW,
|
||||||
|
)
|
||||||
|
keyboard.extensions.append(underglow)
|
||||||
|
|
||||||
|
# Neopixel on XIAO RP2040
|
||||||
|
frontglow = RGB(
|
||||||
|
pixel_pin=board.NEOPIXEL,
|
||||||
|
num_pixels=1,
|
||||||
|
val_limit=100,
|
||||||
|
val_default=25,
|
||||||
|
animation_mode=AnimationModes.RAINBOW,
|
||||||
|
)
|
||||||
|
keyboard.extensions.append(frontglow)
|
||||||
|
|
||||||
|
keyboard.col_pins = (board.D6, board.D8, board.D9)
|
||||||
|
keyboard.row_pins = (board.D1, board.D2, board.D3, board.D7)
|
||||||
|
keyboard.diode_orientation = DiodeOrientation.COL2ROW
|
||||||
|
|
||||||
|
media_keys = MediaKeys()
|
||||||
|
keyboard.extensions.append(media_keys)
|
||||||
|
|
||||||
|
# Matrix 4x3 keymap, 12 keys in total
|
||||||
|
keyboard.keymap = [
|
||||||
|
[
|
||||||
|
KC.N1,
|
||||||
|
KC.N2,
|
||||||
|
KC.N3,
|
||||||
|
KC.N4,
|
||||||
|
KC.N5,
|
||||||
|
KC.N6,
|
||||||
|
KC.N7,
|
||||||
|
KC.N8,
|
||||||
|
KC.N9,
|
||||||
|
KC.N0,
|
||||||
|
KC.A,
|
||||||
|
KC.B,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
keyboard.go()
|
@@ -1,28 +0,0 @@
|
|||||||
# Reviung34
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The Reviung34 is a 34 key keyboard designed by gtips, it is a slightly smaller
|
|
||||||
version of the popular Reviung 39. These "split non-split" keyboards offer a lot
|
|
||||||
of features split keyboards have in terms of comfort and ergonomics but do so in
|
|
||||||
a single-piece package. Many people consider keyboards in this style easier to
|
|
||||||
travel with since you don't have to manage two halves and there is of course no
|
|
||||||
need for a TRRS cable. This board sits somewhere between and Atreus and Corne,
|
|
||||||
and it is extremely comfortable to use.
|
|
||||||
|
|
||||||
Hardware Availability: [PCB & Case Data](https://github.com/gtips/reviung/tree/master)
|
|
||||||
|
|
||||||
Retailers (USA)
|
|
||||||
[Boardsource](https://boardsource.xyz/store)
|
|
||||||
|
|
||||||
Extensions enabled by default
|
|
||||||
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
|
|
||||||
- [RGB matrix](/docs/en/peg_rgb_matrix.md) Light it up
|
|
||||||
|
|
||||||
|
|
||||||
## Microcontroller support
|
|
||||||
|
|
||||||
Update this line in `kb.py` to any supported microcontroller in `kmk/quickpin/pro_micro`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from kmk.quickpin.pro_micro.boardsource_blok import pinout as pins
|
|
@@ -1,37 +0,0 @@
|
|||||||
import board
|
|
||||||
|
|
||||||
from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard
|
|
||||||
from kmk.quickpin.pro_micro.boardsource_blok import pinout as pins
|
|
||||||
from kmk.scanners import DiodeOrientation
|
|
||||||
from kmk.scanners import intify_coordinate as ic
|
|
||||||
|
|
||||||
|
|
||||||
class KMKKeyboard(_KMKKeyboard):
|
|
||||||
row_pins = (
|
|
||||||
pins[19],
|
|
||||||
pins[18],
|
|
||||||
pins[17],
|
|
||||||
pins[16]
|
|
||||||
)
|
|
||||||
col_pins = (
|
|
||||||
pins[6],
|
|
||||||
pins[7],
|
|
||||||
pins[8],
|
|
||||||
pins[9],
|
|
||||||
pins[10],
|
|
||||||
pins[15],
|
|
||||||
pins[14],
|
|
||||||
pins[13],
|
|
||||||
pins[12],
|
|
||||||
)
|
|
||||||
diode_orientation = DiodeOrientation.COLUMNS
|
|
||||||
rgb_pixel_pin = pins[0]
|
|
||||||
rgb_num_pixels = 9
|
|
||||||
led_key_pos = [0,1,2,3,8,4,5,6,7]
|
|
||||||
brightness_limit = 1.0
|
|
||||||
num_pixels = 9
|
|
||||||
coord_mapping = [
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 32
|
|
||||||
,9, 10, 11, 12, 13, 14, 15, 16, 17, 33
|
|
||||||
,18,19, 20, 21, 22, 23, 24, 25, 26, 34
|
|
||||||
,29,30,31,35]
|
|
@@ -1,49 +0,0 @@
|
|||||||
from kb import KMKKeyboard
|
|
||||||
|
|
||||||
from kmk.extensions.peg_rgb_matrix import Rgb_matrix
|
|
||||||
from kmk.extensions.rgb import RGB
|
|
||||||
from kmk.keys import KC
|
|
||||||
from kmk.modules.layers import Layers
|
|
||||||
|
|
||||||
keyboard = KMKKeyboard()
|
|
||||||
|
|
||||||
# Adding extensions
|
|
||||||
# ledmap
|
|
||||||
rgb_ext = Rgb_matrix(ledDisplay=[[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55]],split=False,rightSide=False,disable_auto_write=True)
|
|
||||||
# ledmap
|
|
||||||
layers_ext = Layers()
|
|
||||||
|
|
||||||
keyboard.modules.append(layers_ext)
|
|
||||||
keyboard.extensions.append(rgb_ext)
|
|
||||||
|
|
||||||
# Cleaner key names
|
|
||||||
_______ = KC.TRNS
|
|
||||||
XXXXXXX = KC.NO
|
|
||||||
|
|
||||||
LOWER = KC.MO(2)
|
|
||||||
RAISE = KC.MO(1)
|
|
||||||
|
|
||||||
keyboard.keymap = [
|
|
||||||
[ #QWERTY
|
|
||||||
KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P,\
|
|
||||||
KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN,\
|
|
||||||
KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH,\
|
|
||||||
LOWER, KC.SPC, KC.BSPC, RAISE
|
|
||||||
],
|
|
||||||
[ #RAISE
|
|
||||||
KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0,\
|
|
||||||
KC.TAB, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, XXXXXXX, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC,\
|
|
||||||
KC.LCTL, KC.GRV, KC.LGUI, KC.LALT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.BSLS, KC.QUOT,\
|
|
||||||
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
|
|
||||||
],
|
|
||||||
[ #LOWER
|
|
||||||
KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN,\
|
|
||||||
KC.ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR,\
|
|
||||||
KC.CAPS, KC.TILD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.PIPE, KC.DQT,\
|
|
||||||
XXXXXXX, XXXXXXX, KC.ENT, KC.DEL
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
keyboard.go()
|
|
||||||
|
|
3
boot.py
Executable file → Normal file
3
boot.py
Executable file → Normal file
@@ -1,3 +0,0 @@
|
|||||||
import supervisor
|
|
||||||
|
|
||||||
supervisor.set_next_stack_limit(4096 + 4096)
|
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
KMK is a keyboard focused layer that sits on top of [CircuitPython](https://circuitpython.org/). As such, it should work with most [boards that support CircuitPython](https://circuitpython.org/downloads). KMK requires CircuitPython version 7.0 or above.
|
KMK is a keyboard focused layer that sits on top of [CircuitPython](https://circuitpython.org/). As such, it should work with most [boards that support CircuitPython](https://circuitpython.org/downloads). KMK requires CircuitPython version 7.0 or above.
|
||||||
Known working and recommended devices can be found [here](Officially_Supported_Microcontrollers.md)
|
Known working and recommended devices can be found [here](Officially_Supported_Microcontrollers.md)
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## TL;DR Quick start guide
|
## TL;DR Quick start guide
|
||||||
> To infinity and beyond!
|
> To infinity and beyond!
|
||||||
@@ -13,7 +12,7 @@ Known working and recommended devices can be found [here](Officially_Supported_M
|
|||||||
3. Unzip it and copy the KMK folder and the boot.py file at the root of the USB drive corresponding to your board (often appearing as CIRCUITPY)
|
3. Unzip it and copy the KMK folder and the boot.py file at the root of the USB drive corresponding to your board (often appearing as CIRCUITPY)
|
||||||
4. Create a new *code.py* or *main.py* file in the same root directory (same level as boot.py) with the example content hereunder:
|
4. Create a new *code.py* or *main.py* file in the same root directory (same level as boot.py) with the example content hereunder:
|
||||||
|
|
||||||
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board ! <br>
|
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board !
|
||||||
|
|
||||||
```
|
```
|
||||||
print("Starting")
|
print("Starting")
|
||||||
@@ -45,7 +44,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
6. If it prints the letter "a" (or a "Q" or ... depending on your keyboard layout), you're done!
|
6. If it prints the letter "a" (or a "Q" or ... depending on your keyboard layout), you're done!
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
## Now that you're up and running, you may want to go further...
|
## Now that you're up and running, you may want to go further...
|
||||||
@@ -56,7 +54,7 @@ If your keyboard and microcontroller are officially supported, simply visit the
|
|||||||
|
|
||||||
### You've got another, maybe DIY, board and want to customize KMK for it
|
### You've got another, maybe DIY, board and want to customize KMK for it
|
||||||
First, be sure to understand how your device work, and particularly its specific matrix configuration. You can have a look [here](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) or read the [guide](https://docs.qmk.fm/#/hand_wire) provided by the QMK team for handwired keyboards
|
First, be sure to understand how your device work, and particularly its specific matrix configuration. You can have a look [here](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) or read the [guide](https://docs.qmk.fm/#/hand_wire) provided by the QMK team for handwired keyboards
|
||||||
<br>Once you've got the gist of it:
|
Once you've got the gist of it:
|
||||||
- You can have a look [here](config_and_keymap.md) and [here](keys.md) to start customizing your code.py / main.py file
|
- You can have a look [here](config_and_keymap.md) and [here](keys.md) to start customizing your code.py / main.py file
|
||||||
- There's a [reference](keycodes.md) of the available keycodes
|
- There's a [reference](keycodes.md) of the available keycodes
|
||||||
- [International](international.md) extension adds keys for non US layouts and [Media Keys](media_keys.md) adds keys for ... media
|
- [International](international.md) extension adds keys for non US layouts and [Media Keys](media_keys.md) adds keys for ... media
|
||||||
@@ -69,15 +67,16 @@ And to go even further:
|
|||||||
Want to have fun features such as RGB, split keyboards and more? Check out what builtin [modules](modules.md) and [extensions](extensions.md) can do!
|
Want to have fun features such as RGB, split keyboards and more? Check out what builtin [modules](modules.md) and [extensions](extensions.md) can do!
|
||||||
You can also get ideas from the various [user examples](https://github.com/KMKfw/kmk_firmware/tree/master/user_keymaps) that we provide and dig into our [documentation](README.md).
|
You can also get ideas from the various [user examples](https://github.com/KMKfw/kmk_firmware/tree/master/user_keymaps) that we provide and dig into our [documentation](README.md).
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Additional help and support
|
## Additional help and support
|
||||||
> Roads? Where we're going we don't need roads.
|
> Roads? Where we're going we don't need roads.
|
||||||
|
|
||||||
In case you need it, debugging help can be found [here](debugging.md)
|
In case you need it, debugging help can be found [here](debugging.md)
|
||||||
|
|
||||||
If you need support with KMK or just want to say hi, find us in
|
For asynchronous support and chatter about KMK, [join our Zulip
|
||||||
[#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is
|
community](https://kmkfw.zulipchat.com)!
|
||||||
bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
|
|
||||||
for convenience. If you ask for help in chat or open a bug report, if possible
|
If you ask for help in chat or open a bug report, if possible
|
||||||
make sure your copy of KMK is up-to-date.
|
make sure your copy of KMK is up-to-date.
|
||||||
|
In particular, swing by the Zulip chat *before* opening a GitHub Issue about
|
||||||
|
configuration, documentation, etc. concerns.
|
||||||
|
@@ -6,8 +6,7 @@ to make contributing as easy as possible for everyone while maintaining a consis
|
|||||||
## Contributing Code
|
## Contributing Code
|
||||||
The following guidelines should ensure that any code contributed can be merged in as
|
The following guidelines should ensure that any code contributed can be merged in as
|
||||||
painlessly as possible. If you're unsure how to set up your development environment,
|
painlessly as possible. If you're unsure how to set up your development environment,
|
||||||
feel free to join the chat, [#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh).
|
feel free to [join our Zulip community](https://kmkfw.zulipchat.com).
|
||||||
This channel is bridged to Discord [here](https://discord.gg/QBHUUpeGUd) for convenience.
|
|
||||||
|
|
||||||
### Code Style
|
### Code Style
|
||||||
|
|
||||||
@@ -28,7 +27,12 @@ to Black formatting as documented in `pyproject.toml`)
|
|||||||
Unit tests within the `tests` folder mock various CircuitPython modules to allow
|
Unit tests within the `tests` folder mock various CircuitPython modules to allow
|
||||||
them to be executed in a desktop development environment.
|
them to be executed in a desktop development environment.
|
||||||
|
|
||||||
Execute tests using the command `python -m unittest`.
|
Execute tests using the command `make unit-tests`. The unit-tests target accepts
|
||||||
|
an optional environment variable for specifying a subset of tests with python
|
||||||
|
unittest syntax:
|
||||||
|
```sh
|
||||||
|
make unit-tests TESTS="tests.test_capsword tests.test_hold_tap"
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing Documentation
|
## Contributing Documentation
|
||||||
While KMK welcomes documentation from anyone with and understanding of the issues
|
While KMK welcomes documentation from anyone with and understanding of the issues
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
# Stringy Keymaps
|
# Stringy Keymaps
|
||||||
|
|
||||||
Enables referring to keys by `'NAME'` rather than `KC.NAME`.
|
Enables referring to keys by `'NAME'` rather than `KC.NAME`.\
|
||||||
|
This extension allows for a seamless integration of both string-based key references and standard keycodes.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@@ -13,6 +14,9 @@ from kmk.extensions.stringy_keymaps import StringyKeymaps
|
|||||||
# Indexed
|
# Indexed
|
||||||
# keyboard.keymap = [[ KC['A'], KC['B'], KC['RESET'] ]]
|
# keyboard.keymap = [[ KC['A'], KC['B'], KC['RESET'] ]]
|
||||||
|
|
||||||
|
# String names mixed with normal keycodes
|
||||||
|
# keyboard.keymap = [[ 'A' , KC.B, KC.RESET ]]
|
||||||
|
|
||||||
# String names
|
# String names
|
||||||
keyboard.keymap = [[ 'A' , 'B', 'RESET' ]]
|
keyboard.keymap = [[ 'A' , 'B', 'RESET' ]]
|
||||||
|
|
||||||
@@ -27,3 +31,5 @@ keyboard.extensions.append(stringyKeymaps)
|
|||||||
|
|
||||||
It should be noted that these are **not** ASCII. The string is **not** what
|
It should be noted that these are **not** ASCII. The string is **not** what
|
||||||
will be sent to the computer. The examples above have no functional difference.
|
will be sent to the computer. The examples above have no functional difference.
|
||||||
|
|
||||||
|
When utilizing argumented keys, such as `KC.MO(layer)`, it's not possible to use a string like `'MO(layer)'` instead employ the standard notation of e.g. `KC.MO(1)` in your keymap.
|
@@ -9,9 +9,7 @@ Linux).
|
|||||||
Given `make` and `rsync` are available on your system (in `$PATH`), the
|
Given `make` and `rsync` are available on your system (in `$PATH`), the
|
||||||
following will copy the `kmk` tree to your CircuitPython device, and will copy
|
following will copy the `kmk` tree to your CircuitPython device, and will copy
|
||||||
the file defined as `USER_KEYMAP` as your `main.py`. It will also copy our
|
the file defined as `USER_KEYMAP` as your `main.py`. It will also copy our
|
||||||
`boot.py`, which allocates a larger stack size (simply - more of the device's
|
`boot.py`. If any of these files exist on your CircuitPython device already, they
|
||||||
RAM will be available to KMK and your keyboard config) than CircuitPython's
|
|
||||||
default. If any of these files exist on your CircuitPython device already, they
|
|
||||||
will be overwritten without a prompt.
|
will be overwritten without a prompt.
|
||||||
|
|
||||||
If you get permissions errors here, **don't run make as root or with sudo**. See
|
If you get permissions errors here, **don't run make as root or with sudo**. See
|
||||||
|
@@ -84,7 +84,7 @@ class Layers(_Layers):
|
|||||||
last_top_layer = 0
|
last_top_layer = 0
|
||||||
hues = (4, 20, 69)
|
hues = (4, 20, 69)
|
||||||
|
|
||||||
def after_hid_send(keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
if keyboard.active_layers[0] != self.last_top_layer:
|
if keyboard.active_layers[0] != self.last_top_layer:
|
||||||
self.last_top_layer = keyboard.active_layers[0]
|
self.last_top_layer = keyboard.active_layers[0]
|
||||||
rgb.set_hsv_fill(self.hues[self.last_top_layer], 255, 255)
|
rgb.set_hsv_fill(self.hues[self.last_top_layer], 255, 255)
|
||||||
|
@@ -15,6 +15,8 @@ keyboard.modules.append(MouseKeys())
|
|||||||
| `KC.MB_LMB` | Left mouse button |
|
| `KC.MB_LMB` | Left mouse button |
|
||||||
| `KC.MB_RMB` | Right mouse button |
|
| `KC.MB_RMB` | Right mouse button |
|
||||||
| `KC.MB_MMB` | Middle mouse button |
|
| `KC.MB_MMB` | Middle mouse button |
|
||||||
|
| `KC.MB_BTN4` | mouse button 4 |
|
||||||
|
| `KC.MB_BTN5` | mouse button 5 |
|
||||||
| `KC.MW_UP` | Mouse wheel up |
|
| `KC.MW_UP` | Mouse wheel up |
|
||||||
| `KC.MW_DOWN`, `KC.MW_DN` | Mouse wheel down |
|
| `KC.MW_DOWN`, `KC.MW_DN` | Mouse wheel down |
|
||||||
| `KC.MS_UP` | Move mouse cursor up |
|
| `KC.MS_UP` | Move mouse cursor up |
|
||||||
|
Before Width: | Height: | Size: 400 KiB After Width: | Height: | Size: 400 KiB |
@@ -15,7 +15,7 @@ microcontrollers with only a single line change and less mistakes.
|
|||||||
|
|
||||||
## Pro micro footprint pinout
|
## Pro micro footprint pinout
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Support
|
# Support
|
||||||
|
|
||||||
If you need support with KMK or just want to say hi, find us in [#kmkfw:klar.sh
|
For asynchronous support and chatter about KMK, [join our Zulip
|
||||||
on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is bridged to
|
community](https://kmkfw.zulipchat.com)!
|
||||||
Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
|
|
||||||
for convenience.
|
|
||||||
|
|
||||||
If you ask for help in chat or open a bug report, if possible
|
If you ask for help in chat or open a bug report, if possible
|
||||||
make sure your copy of KMK is up-to-date.
|
make sure your copy of KMK is up-to-date.
|
||||||
|
In particular, swing by the Zulip chat *before* opening a GitHub Issue about
|
||||||
|
configuration, documentation, etc. concerns.
|
||||||
|
@@ -9,7 +9,6 @@ KMK は[CircuitPython](https://circuitpython.org/)の上に配置されるキー
|
|||||||
|
|
||||||
CircuitPython の最適化バージョン(特定のボードの容量制限に対処した、プリインストールされた関連モジュールの選択が可能なバージョン)も提供しています。
|
CircuitPython の最適化バージョン(特定のボードの容量制限に対処した、プリインストールされた関連モジュールの選択が可能なバージョン)も提供しています。
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## TL;DR クイックスタートガイド
|
## TL;DR クイックスタートガイド
|
||||||
> To infinity and beyond!
|
> To infinity and beyond!
|
||||||
@@ -25,7 +24,7 @@ CircuitPython の最適化バージョン(特定のボードの容量制限に
|
|||||||
|
|
||||||
4. 同じルートディレクトリー(boot.py と同レベル)に新規で*code.py* または *main.py*のファイルを作成する。中身は以下の例とする。
|
4. 同じルートディレクトリー(boot.py と同レベル)に新規で*code.py* または *main.py*のファイルを作成する。中身は以下の例とする。
|
||||||
|
|
||||||
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい!<br>
|
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -56,8 +55,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
2. "A"や"Q"(キーボードのレイアウトによって異なる)が表示されたら、完成!
|
2. "A"や"Q"(キーボードのレイアウトによって異なる)が表示されたら、完成!
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
## とりあえず一通り動くようになったので、もっとに先へ進みたい場合
|
## とりあえず一通り動くようになったので、もっとに先へ進みたい場合
|
||||||
> This is your last chance. After this, there is no turning back. You take the blue pill—the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill—you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember: all I'm offering is the truth. Nothing more.
|
> This is your last chance. After this, there is no turning back. You take the blue pill—the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill—you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember: all I'm offering is the truth. Nothing more.
|
||||||
@@ -72,7 +69,7 @@ if __name__ == '__main__':
|
|||||||
最初にデバイスの動作や具体的なマトリックス構成についてしっかり理解してください。
|
最初にデバイスの動作や具体的なマトリックス構成についてしっかり理解してください。
|
||||||
QMK チームが提供している手配線キーボード用の[ガイド](https://docs.qmk.fm/#/hand_wire)と[ドキュメント](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) を確認できます。
|
QMK チームが提供している手配線キーボード用の[ガイド](https://docs.qmk.fm/#/hand_wire)と[ドキュメント](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) を確認できます。
|
||||||
|
|
||||||
<br>要旨をつかめてきたら:
|
要旨をつかめてきたら:
|
||||||
- [ここ](config_and_keymap.md) と [ここ](keys.md)を見て、code.py / main.py ファイルをカスタイマイズできます。
|
- [ここ](config_and_keymap.md) と [ここ](keys.md)を見て、code.py / main.py ファイルをカスタイマイズできます。
|
||||||
|
|
||||||
- 使用可能なキーコードの[リファレンス](keycodes.md)があります。
|
- 使用可能なキーコードの[リファレンス](keycodes.md)があります。
|
||||||
@@ -89,15 +86,13 @@ RGB や分裂型などの機能を楽しめたい場合は、ビルトイン[モ
|
|||||||
|
|
||||||
私たちが提供する、いろんな [ユーザー事例](https://github.com/KMKfw/user_keymaps)や[ドキュメント](https://github.com/KMKfw/kmk_firmware/tree/master/docs)からアイデアを得ることもできます。
|
私たちが提供する、いろんな [ユーザー事例](https://github.com/KMKfw/user_keymaps)や[ドキュメント](https://github.com/KMKfw/kmk_firmware/tree/master/docs)からアイデアを得ることもできます。
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## ヘルプ/サポート
|
## ヘルプ/サポート
|
||||||
> Roads? Where we're going we don't need roads.
|
> Roads? Where we're going we don't need roads.
|
||||||
|
|
||||||
デバッグについてのヘルプが必要な場合は[こちら](debugging.md)。
|
デバッグについてのヘルプが必要な場合は[こちら](debugging.md)。
|
||||||
|
|
||||||
KMK についてサポートが必要な場合や、コミュニケーションをとりたい場合は[こちら](https://matrix.to/#/#kmkfw:klar.sh)。
|
KMK についてサポートが必要な場合や、コミュニケーションをとりたい場合は[こちら](https://kmkfw.zulipchat.com)。
|
||||||
このチャネルは[Discord](https://discordapp.com/widget?id=493256121075761173&theme=dark) からも見ることができます。
|
|
||||||
|
|
||||||
チャットで助けを求める場合やバグ レポートを開く場合は、可能であれば KMK
|
チャットで助けを求める場合やバグ レポートを開く場合は、可能であれば KMK
|
||||||
のコピーが最新であることを確認してください。
|
のコピーが最新であることを確認してください。
|
||||||
|
@@ -13,7 +13,6 @@ Também fornecemos uma versão de CircuitPython otimizada para teclados
|
|||||||
(simplificada para lidar com os limites de certas placas e com a seleção dos
|
(simplificada para lidar com os limites de certas placas e com a seleção dos
|
||||||
módulos relevantes pré-instalados). Se você estiver se perguntando por que usar
|
módulos relevantes pré-instalados). Se você estiver se perguntando por que usar
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Guia Rápido
|
## Guia Rápido
|
||||||
> Ao Infinito e Além!
|
> Ao Infinito e Além!
|
||||||
@@ -30,7 +29,7 @@ módulos relevantes pré-instalados). Se você estiver se perguntando por que us
|
|||||||
4. Crie um novo arquivo *code.py* ou *main.py* no mesmo diretório raiz (no
|
4. Crie um novo arquivo *code.py* ou *main.py* no mesmo diretório raiz (no
|
||||||
mesmo nível de boot.py) com o exemplo contido abaixo:
|
mesmo nível de boot.py) com o exemplo contido abaixo:
|
||||||
|
|
||||||
***IMPORTANTE:*** adapte os pinos GP0 / GP1 para a tua placa específica! <br>
|
***IMPORTANTE:*** adapte os pinos GP0 / GP1 para a tua placa específica!
|
||||||
|
|
||||||
```
|
```
|
||||||
print("Starting")
|
print("Starting")
|
||||||
@@ -61,7 +60,6 @@ if __name__ == '__main__':
|
|||||||
6. Se ela imprimir um "A" (ou um "Q" ou o que depender do teu layout de
|
6. Se ela imprimir um "A" (ou um "Q" ou o que depender do teu layout de
|
||||||
teclado), você conseguiu!
|
teclado), você conseguiu!
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
## Agora que tudo está no seu lugar, você pode querer ir além...
|
## Agora que tudo está no seu lugar, você pode querer ir além...
|
||||||
@@ -88,7 +86,7 @@ sua configuração matricial específica. Você pode observar
|
|||||||
[guia](https://docs.qmk.fm/#/hand_wire) feito pelo time da QMK para teclados
|
[guia](https://docs.qmk.fm/#/hand_wire) feito pelo time da QMK para teclados
|
||||||
artesanais.
|
artesanais.
|
||||||
|
|
||||||
<br>Uma vez que você compreendeu a essência da coisa:
|
Uma vez que você compreendeu a essência da coisa:
|
||||||
- Você pode dar uma olhada [aqui](config_and_keymap.md) e [aqui](keys.md) para
|
- Você pode dar uma olhada [aqui](config_and_keymap.md) e [aqui](keys.md) para
|
||||||
começar a customizar seu arquivo code.py / main.py.
|
começar a customizar seu arquivo code.py / main.py.
|
||||||
- Eis uma [referência](keycodes.md) dos códigos de teclas (*keycodes*)
|
- Eis uma [referência](keycodes.md) dos códigos de teclas (*keycodes*)
|
||||||
@@ -115,7 +113,6 @@ Você também pode obter ideias dos vários [exemplos de
|
|||||||
usuários](https://github.com/KMKfw/user_keymaps) que fornecemos e fuce nossa
|
usuários](https://github.com/KMKfw/user_keymaps) que fornecemos e fuce nossa
|
||||||
[documentação](https://github.com/KMKfw/kmk_firmware/tree/master/docs).
|
[documentação](https://github.com/KMKfw/kmk_firmware/tree/master/docs).
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Ajuda e Suporte Adicionais
|
## Ajuda e Suporte Adicionais
|
||||||
> Estradas? Para onde vamos, estradas são desnecessárias.
|
> Estradas? Para onde vamos, estradas são desnecessárias.
|
||||||
@@ -123,8 +120,6 @@ usuários](https://github.com/KMKfw/user_keymaps) que fornecemos e fuce nossa
|
|||||||
Caso precise, ajuda para depuração pode ser encontrada [aqui](debugging.md).
|
Caso precise, ajuda para depuração pode ser encontrada [aqui](debugging.md).
|
||||||
|
|
||||||
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
|
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
|
||||||
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal
|
canal [kmkfw no Zulip](https://kmkfw.zulipchat.com).
|
||||||
tem uma ponte no Discord
|
Se você precisa de ajuda ou pretende abrir um bug report, se
|
||||||
[aqui](https://discordapp.com/widget?id=493256121075761173&theme=dark) por
|
|
||||||
conveniência. Se você precisa de ajuda ou pretende abrir um bug report, se
|
|
||||||
possível se possível, verifique se sua cópia do KMK está atualizada.
|
possível se possível, verifique se sua cópia do KMK está atualizada.
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
# Suporte
|
# Suporte
|
||||||
|
|
||||||
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
|
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
|
||||||
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal
|
canal [no Zulip](https://kmkfw.zulipchat.com).
|
||||||
tem uma ponte no Discord
|
|
||||||
[aqui](https://discordapp.com/widget?id=493256121075761173&theme=dark) por
|
|
||||||
conveniência.
|
|
||||||
|
|
||||||
Se você precisa de ajuda ou pretende abrir um bug report, se
|
Se você precisa de ajuda ou pretende abrir um bug report, se
|
||||||
possível se possível, verifique se sua cópia do KMK está atualizada.
|
possível se possível, verifique se sua cópia do KMK está atualizada.
|
||||||
|
@@ -59,7 +59,7 @@ def hsv_to_rgb(hue, sat, val):
|
|||||||
return (r >> 8), (g >> 8), (b >> 8)
|
return (r >> 8), (g >> 8), (b >> 8)
|
||||||
|
|
||||||
|
|
||||||
def hsv_to_rgbw(self, hue, sat, val):
|
def hsv_to_rgbw(hue, sat, val):
|
||||||
'''
|
'''
|
||||||
Converts HSV values, and returns a tuple of RGBW values
|
Converts HSV values, and returns a tuple of RGBW values
|
||||||
:param hue:
|
:param hue:
|
||||||
|
@@ -127,3 +127,13 @@ def ble_refresh(key, keyboard, *args, **kwargs):
|
|||||||
keyboard._hid_helper.stop_advertising()
|
keyboard._hid_helper.stop_advertising()
|
||||||
keyboard._hid_helper.start_advertising()
|
keyboard._hid_helper.start_advertising()
|
||||||
return keyboard
|
return keyboard
|
||||||
|
|
||||||
|
|
||||||
|
def ble_disconnect(key, keyboard, *args, **kwargs):
|
||||||
|
from kmk.hid import HIDModes
|
||||||
|
|
||||||
|
if keyboard.hid_type != HIDModes.BLE:
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
keyboard._hid_helper.clear_bonds()
|
||||||
|
return keyboard
|
||||||
|
95
kmk/hid.py
95
kmk/hid.py
@@ -4,7 +4,8 @@ from micropython import const
|
|||||||
|
|
||||||
from storage import getmount
|
from storage import getmount
|
||||||
|
|
||||||
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey
|
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey, MouseKey
|
||||||
|
from kmk.utils import clamp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from adafruit_ble import BLERadio
|
from adafruit_ble import BLERadio
|
||||||
@@ -68,6 +69,14 @@ class AbstractHID:
|
|||||||
self.report_mods = memoryview(self._evt)[1:2]
|
self.report_mods = memoryview(self._evt)[1:2]
|
||||||
self.report_non_mods = memoryview(self._evt)[3:]
|
self.report_non_mods = memoryview(self._evt)[3:]
|
||||||
|
|
||||||
|
self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
|
||||||
|
self._cc_report[0] = HIDReportTypes.CONSUMER
|
||||||
|
self._cc_pending = False
|
||||||
|
|
||||||
|
self._pd_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
|
||||||
|
self._pd_report[0] = HIDReportTypes.MOUSE
|
||||||
|
self._pd_pending = False
|
||||||
|
|
||||||
self.post_init()
|
self.post_init()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -76,47 +85,27 @@ class AbstractHID:
|
|||||||
def post_init(self):
|
def post_init(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_report(self, keys_pressed):
|
def create_report(self, keys_pressed, axes):
|
||||||
self.clear_all()
|
self.clear_all()
|
||||||
|
|
||||||
consumer_key = None
|
|
||||||
for key in keys_pressed:
|
|
||||||
if isinstance(key, ConsumerKey):
|
|
||||||
consumer_key = key
|
|
||||||
break
|
|
||||||
|
|
||||||
reporting_device = self.report_device[0]
|
|
||||||
needed_reporting_device = HIDReportTypes.KEYBOARD
|
|
||||||
|
|
||||||
if consumer_key:
|
|
||||||
needed_reporting_device = HIDReportTypes.CONSUMER
|
|
||||||
|
|
||||||
if reporting_device != needed_reporting_device:
|
|
||||||
# If we are about to change reporting devices, release
|
|
||||||
# all keys and close our proverbial tab on the existing
|
|
||||||
# device, or keys will get stuck (mostly when releasing
|
|
||||||
# media/consumer keys)
|
|
||||||
self.send()
|
|
||||||
|
|
||||||
self.report_device[0] = needed_reporting_device
|
|
||||||
|
|
||||||
if consumer_key:
|
|
||||||
self.add_key(consumer_key)
|
|
||||||
else:
|
|
||||||
for key in keys_pressed:
|
for key in keys_pressed:
|
||||||
if key.code >= FIRST_KMK_INTERNAL_KEY:
|
if key.code >= FIRST_KMK_INTERNAL_KEY:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(key, ModifierKey):
|
if isinstance(key, ModifierKey):
|
||||||
self.add_modifier(key)
|
self.add_modifier(key)
|
||||||
|
elif isinstance(key, ConsumerKey):
|
||||||
|
self.add_cc(key)
|
||||||
|
elif isinstance(key, MouseKey):
|
||||||
|
self.add_pd(key)
|
||||||
else:
|
else:
|
||||||
self.add_key(key)
|
self.add_key(key)
|
||||||
|
|
||||||
if key.has_modifiers:
|
if key.has_modifiers:
|
||||||
for mod in key.has_modifiers:
|
for mod in key.has_modifiers:
|
||||||
self.add_modifier(mod)
|
self.add_modifier(mod)
|
||||||
|
|
||||||
return self
|
for axis in axes:
|
||||||
|
self.move_axis(axis)
|
||||||
|
|
||||||
def hid_send(self, evt):
|
def hid_send(self, evt):
|
||||||
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
|
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
|
||||||
@@ -131,12 +120,24 @@ class AbstractHID:
|
|||||||
self._prev_evt[:] = self._evt
|
self._prev_evt[:] = self._evt
|
||||||
self.hid_send(self._evt)
|
self.hid_send(self._evt)
|
||||||
|
|
||||||
|
if self._cc_pending:
|
||||||
|
self.hid_send(self._cc_report)
|
||||||
|
self._cc_pending = False
|
||||||
|
|
||||||
|
if self._pd_pending:
|
||||||
|
self.hid_send(self._pd_report)
|
||||||
|
self._pd_pending = False
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear_all(self):
|
def clear_all(self):
|
||||||
for idx, _ in enumerate(self.report_keys):
|
for idx, _ in enumerate(self.report_keys):
|
||||||
self.report_keys[idx] = 0x00
|
self.report_keys[idx] = 0x00
|
||||||
|
|
||||||
|
self.remove_cc()
|
||||||
|
self.remove_pd()
|
||||||
|
self.clear_axis()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear_non_modifiers(self):
|
def clear_non_modifiers(self):
|
||||||
@@ -175,9 +176,6 @@ class AbstractHID:
|
|||||||
|
|
||||||
where_to_place = self.report_non_mods
|
where_to_place = self.report_non_mods
|
||||||
|
|
||||||
if self.report_device[0] == HIDReportTypes.CONSUMER:
|
|
||||||
where_to_place = self.report_keys
|
|
||||||
|
|
||||||
for idx, _ in enumerate(where_to_place):
|
for idx, _ in enumerate(where_to_place):
|
||||||
if where_to_place[idx] == 0x00:
|
if where_to_place[idx] == 0x00:
|
||||||
where_to_place[idx] = key.code
|
where_to_place[idx] = key.code
|
||||||
@@ -193,15 +191,44 @@ class AbstractHID:
|
|||||||
def remove_key(self, key):
|
def remove_key(self, key):
|
||||||
where_to_place = self.report_non_mods
|
where_to_place = self.report_non_mods
|
||||||
|
|
||||||
if self.report_device[0] == HIDReportTypes.CONSUMER:
|
|
||||||
where_to_place = self.report_keys
|
|
||||||
|
|
||||||
for idx, _ in enumerate(where_to_place):
|
for idx, _ in enumerate(where_to_place):
|
||||||
if where_to_place[idx] == key.code:
|
if where_to_place[idx] == key.code:
|
||||||
where_to_place[idx] = 0x00
|
where_to_place[idx] = 0x00
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def add_cc(self, cc):
|
||||||
|
# Add (or write over) consumer control report. There can only be one CC
|
||||||
|
# active at any time.
|
||||||
|
memoryview(self._cc_report)[1:3] = cc.code.to_bytes(2, 'little')
|
||||||
|
self._cc_pending = True
|
||||||
|
|
||||||
|
def remove_cc(self):
|
||||||
|
# Remove consumer control report.
|
||||||
|
report = memoryview(self._cc_report)[1:3]
|
||||||
|
if report != b'\x00\x00':
|
||||||
|
report[:] = b'\x00\x00'
|
||||||
|
self._cc_pending = True
|
||||||
|
|
||||||
|
def add_pd(self, key):
|
||||||
|
self._pd_report[1] |= key.code
|
||||||
|
self._pd_pending = True
|
||||||
|
|
||||||
|
def remove_pd(self):
|
||||||
|
if self._pd_report[1]:
|
||||||
|
self._pd_pending = True
|
||||||
|
self._pd_report[1] = 0x00
|
||||||
|
|
||||||
|
def move_axis(self, axis):
|
||||||
|
delta = clamp(axis.delta, -127, 127)
|
||||||
|
axis.delta -= delta
|
||||||
|
self._pd_report[axis.code + 2] = 0xFF & delta
|
||||||
|
self._pd_pending = True
|
||||||
|
|
||||||
|
def clear_axis(self):
|
||||||
|
for idx in range(2, len(self._pd_report)):
|
||||||
|
self._pd_report[idx] = 0x00
|
||||||
|
|
||||||
|
|
||||||
class USBHID(AbstractHID):
|
class USBHID(AbstractHID):
|
||||||
REPORT_BYTES = 9
|
REPORT_BYTES = 9
|
||||||
|
90
kmk/keys.py
90
kmk/keys.py
@@ -20,6 +20,7 @@ class KeyType:
|
|||||||
SIMPLE = const(0)
|
SIMPLE = const(0)
|
||||||
MODIFIER = const(1)
|
MODIFIER = const(1)
|
||||||
CONSUMER = const(2)
|
CONSUMER = const(2)
|
||||||
|
MOUSE = const(3)
|
||||||
|
|
||||||
|
|
||||||
FIRST_KMK_INTERNAL_KEY = const(1000)
|
FIRST_KMK_INTERNAL_KEY = const(1000)
|
||||||
@@ -33,6 +34,29 @@ ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
|
|||||||
debug = Debug(__name__)
|
debug = Debug(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Axis:
|
||||||
|
def __init__(self, code: int) -> None:
|
||||||
|
self.code = code
|
||||||
|
self.delta = 0
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'Axis(code={self.code}, delta={self.delta})'
|
||||||
|
|
||||||
|
def move(self, keyboard: Keyboard, delta: int):
|
||||||
|
self.delta += delta
|
||||||
|
if self.delta:
|
||||||
|
keyboard.axes.add(self)
|
||||||
|
keyboard.hid_pending = True
|
||||||
|
else:
|
||||||
|
keyboard.axes.discard(self)
|
||||||
|
|
||||||
|
|
||||||
|
class AX:
|
||||||
|
W = Axis(2)
|
||||||
|
X = Axis(0)
|
||||||
|
Y = Axis(1)
|
||||||
|
|
||||||
|
|
||||||
def maybe_make_key(
|
def maybe_make_key(
|
||||||
code: Optional[int],
|
code: Optional[int],
|
||||||
names: Tuple[str, ...],
|
names: Tuple[str, ...],
|
||||||
@@ -340,6 +364,7 @@ def maybe_make_unicode_key(candidate: str) -> Optional[Key]:
|
|||||||
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
|
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
|
||||||
keys = (
|
keys = (
|
||||||
((('BLE_REFRESH',), handlers.ble_refresh)),
|
((('BLE_REFRESH',), handlers.ble_refresh)),
|
||||||
|
((('BLE_DISCONNECT',), handlers.ble_disconnect)),
|
||||||
((('BOOTLOADER',), handlers.bootloader)),
|
((('BOOTLOADER',), handlers.bootloader)),
|
||||||
((('DEBUG', 'DBG'), handlers.debug_pressed)),
|
((('DEBUG', 'DBG'), handlers.debug_pressed)),
|
||||||
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
|
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
|
||||||
@@ -400,43 +425,62 @@ KEY_GENERATORS = (
|
|||||||
|
|
||||||
|
|
||||||
class KeyAttrDict:
|
class KeyAttrDict:
|
||||||
__cache = {}
|
# Instead of relying on the uncontrollable availability of a big chunk of
|
||||||
|
# contiguous memory for key caching, we can manually fragment the cache into
|
||||||
|
# reasonably small partitions. The partition size is chosen from the magic
|
||||||
|
# values of CPs hash allocation sizes.
|
||||||
|
# (https://github.com/adafruit/circuitpython/blob/main/py/map.c, 2023-02)
|
||||||
|
__partition_size = 37
|
||||||
|
__cache = [{}]
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self.__cache.__iter__()
|
for partition in self.__cache:
|
||||||
|
for name in partition:
|
||||||
|
yield name
|
||||||
|
|
||||||
def __setitem__(self, key: str, value: Key):
|
def __setitem__(self, name: str, key: Key):
|
||||||
self.__cache.__setitem__(key, value)
|
# Overwrite existing reference.
|
||||||
|
for partition in self.__cache:
|
||||||
|
if name in partition:
|
||||||
|
partition[name] = key
|
||||||
|
return key
|
||||||
|
|
||||||
def __getattr__(self, key: Key):
|
# Insert new reference.
|
||||||
return self.__getitem__(key)
|
if len(self.__cache[-1]) >= self.__partition_size:
|
||||||
|
self.__cache.append({})
|
||||||
|
self.__cache[-1][name] = key
|
||||||
|
return key
|
||||||
|
|
||||||
def get(self, key: Key, default: Optional[Key] = None):
|
def __getattr__(self, name: str):
|
||||||
|
return self.__getitem__(name)
|
||||||
|
|
||||||
|
def get(self, name: str, default: Optional[Key] = None):
|
||||||
try:
|
try:
|
||||||
return self.__getitem__(key)
|
return self.__getitem__(name)
|
||||||
except Exception:
|
except Exception:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.__cache.clear()
|
self.__cache.clear()
|
||||||
|
self.__cache.append({})
|
||||||
|
|
||||||
def __getitem__(self, key: Key):
|
def __getitem__(self, name: str):
|
||||||
try:
|
for partition in self.__cache:
|
||||||
return self.__cache[key]
|
if name in partition:
|
||||||
except KeyError:
|
return partition[name]
|
||||||
pass
|
|
||||||
|
|
||||||
for func in KEY_GENERATORS:
|
for func in KEY_GENERATORS:
|
||||||
maybe_key = func(key)
|
maybe_key = func(name)
|
||||||
if maybe_key:
|
if maybe_key:
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
raise ValueError(f'Invalid key: {key}')
|
if not maybe_key:
|
||||||
|
raise ValueError(f'Invalid key: {name}')
|
||||||
|
|
||||||
if debug.enabled:
|
if debug.enabled:
|
||||||
debug(f'{key}: {maybe_key}')
|
debug(f'{name}: {maybe_key}')
|
||||||
|
|
||||||
return self.__cache[key]
|
return maybe_key
|
||||||
|
|
||||||
|
|
||||||
# Global state, will be filled in throughout this file, and
|
# Global state, will be filled in throughout this file, and
|
||||||
@@ -669,6 +713,10 @@ class ConsumerKey(Key):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MouseKey(Key):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def make_key(
|
def make_key(
|
||||||
code: Optional[int] = None,
|
code: Optional[int] = None,
|
||||||
names: Tuple[str, ...] = tuple(), # NOQA
|
names: Tuple[str, ...] = tuple(), # NOQA
|
||||||
@@ -699,6 +747,8 @@ def make_key(
|
|||||||
constructor = ModifierKey
|
constructor = ModifierKey
|
||||||
elif type == KeyType.CONSUMER:
|
elif type == KeyType.CONSUMER:
|
||||||
constructor = ConsumerKey
|
constructor = ConsumerKey
|
||||||
|
elif type == KeyType.MOUSE:
|
||||||
|
constructor = MouseKey
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unrecognized key type')
|
raise ValueError('Unrecognized key type')
|
||||||
|
|
||||||
@@ -731,6 +781,10 @@ def make_consumer_key(*args, **kwargs) -> Key:
|
|||||||
return make_key(*args, **kwargs, type=KeyType.CONSUMER)
|
return make_key(*args, **kwargs, type=KeyType.CONSUMER)
|
||||||
|
|
||||||
|
|
||||||
|
def make_mouse_key(*args, **kwargs) -> Key:
|
||||||
|
return make_key(*args, **kwargs, type=KeyType.MOUSE)
|
||||||
|
|
||||||
|
|
||||||
# Argumented keys are implicitly internal, so auto-gen of code
|
# Argumented keys are implicitly internal, so auto-gen of code
|
||||||
# is almost certainly the best plan here
|
# is almost certainly the best plan here
|
||||||
def make_argumented_key(
|
def make_argumented_key(
|
||||||
|
@@ -49,6 +49,7 @@ class KMKKeyboard:
|
|||||||
#####
|
#####
|
||||||
# Internal State
|
# Internal State
|
||||||
keys_pressed = set()
|
keys_pressed = set()
|
||||||
|
axes = set()
|
||||||
_coordkeys_pressed = {}
|
_coordkeys_pressed = {}
|
||||||
hid_type = HIDModes.USB
|
hid_type = HIDModes.USB
|
||||||
secondary_hid_type = None
|
secondary_hid_type = None
|
||||||
@@ -88,6 +89,7 @@ class KMKKeyboard:
|
|||||||
f' unicode_mode={self.unicode_mode}, ',
|
f' unicode_mode={self.unicode_mode}, ',
|
||||||
f'_hid_helper={self._hid_helper},\n',
|
f'_hid_helper={self._hid_helper},\n',
|
||||||
f' keys_pressed={self.keys_pressed},\n',
|
f' keys_pressed={self.keys_pressed},\n',
|
||||||
|
f' axes={self.axes},\n',
|
||||||
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
|
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
|
||||||
f' hid_pending={self.hid_pending}, ',
|
f' hid_pending={self.hid_pending}, ',
|
||||||
f'active_layers={self.active_layers}, ',
|
f'active_layers={self.active_layers}, ',
|
||||||
@@ -102,15 +104,24 @@ class KMKKeyboard:
|
|||||||
debug(f'keys_pressed={self.keys_pressed}')
|
debug(f'keys_pressed={self.keys_pressed}')
|
||||||
|
|
||||||
def _send_hid(self) -> None:
|
def _send_hid(self) -> None:
|
||||||
if self._hid_send_enabled:
|
if not self._hid_send_enabled:
|
||||||
hid_report = self._hid_helper.create_report(self.keys_pressed)
|
return
|
||||||
|
|
||||||
|
if self.axes and debug.enabled:
|
||||||
|
debug(f'axes={self.axes}')
|
||||||
|
|
||||||
|
self._hid_helper.create_report(self.keys_pressed, self.axes)
|
||||||
try:
|
try:
|
||||||
hid_report.send()
|
self._hid_helper.send()
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
if debug.enabled:
|
if debug.enabled:
|
||||||
debug(f'HidNotFound(HIDReportType={e})')
|
debug(f'HidNotFound(HIDReportType={e})')
|
||||||
|
|
||||||
self.hid_pending = False
|
self.hid_pending = False
|
||||||
|
|
||||||
|
for axis in self.axes:
|
||||||
|
axis.move(self, 0)
|
||||||
|
|
||||||
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
|
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
|
||||||
if kevent is not None:
|
if kevent is not None:
|
||||||
self._on_matrix_changed(kevent)
|
self._on_matrix_changed(kevent)
|
||||||
|
@@ -4,9 +4,9 @@ import microcontroller
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from kmk.keys import AX
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
from kmk.modules.adns9800_firmware import firmware
|
from kmk.modules.adns9800_firmware import firmware
|
||||||
from kmk.modules.mouse_keys import PointingDevice
|
|
||||||
|
|
||||||
|
|
||||||
class REG:
|
class REG:
|
||||||
@@ -70,7 +70,6 @@ class ADNS9800(Module):
|
|||||||
DIR_READ = 0x7F
|
DIR_READ = 0x7F
|
||||||
|
|
||||||
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
|
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
|
||||||
self.pointing_device = PointingDevice()
|
|
||||||
self.cs = digitalio.DigitalInOut(cs)
|
self.cs = digitalio.DigitalInOut(cs)
|
||||||
self.cs.direction = digitalio.Direction.OUTPUT
|
self.cs.direction = digitalio.Direction.OUTPUT
|
||||||
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
|
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
|
||||||
@@ -203,27 +202,14 @@ class ADNS9800(Module):
|
|||||||
if self.invert_y:
|
if self.invert_y:
|
||||||
delta_y *= -1
|
delta_y *= -1
|
||||||
|
|
||||||
if delta_x < 0:
|
if delta_x:
|
||||||
self.pointing_device.report_x[0] = (delta_x & 0xFF) | 0x80
|
AX.X.move(delta_x)
|
||||||
else:
|
|
||||||
self.pointing_device.report_x[0] = delta_x & 0xFF
|
|
||||||
|
|
||||||
if delta_y < 0:
|
if delta_y:
|
||||||
self.pointing_device.report_y[0] = (delta_y & 0xFF) | 0x80
|
AX.Y.move(delta_y)
|
||||||
else:
|
|
||||||
self.pointing_device.report_y[0] = delta_y & 0xFF
|
|
||||||
|
|
||||||
if keyboard.debug_enabled:
|
if keyboard.debug_enabled:
|
||||||
print('Delta: ', delta_x, ' ', delta_y)
|
print('Delta: ', delta_x, ' ', delta_y)
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
if self.pointing_device.hid_pending:
|
|
||||||
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
self.pointing_device.report_x[0] = 0
|
|
||||||
self.pointing_device.report_y[0] = 0
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
|
@@ -4,8 +4,8 @@ Extension handles usage of AS5013 by AMS
|
|||||||
|
|
||||||
from supervisor import ticks_ms
|
from supervisor import ticks_ms
|
||||||
|
|
||||||
|
from kmk.keys import AX
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
from kmk.modules.mouse_keys import PointingDevice
|
|
||||||
|
|
||||||
I2C_ADDRESS = 0x40
|
I2C_ADDRESS = 0x40
|
||||||
I2X_ALT_ADDRESS = 0x41
|
I2X_ALT_ADDRESS = 0x41
|
||||||
@@ -44,7 +44,6 @@ class Easypoint(Module):
|
|||||||
self._i2c_bus = i2c
|
self._i2c_bus = i2c
|
||||||
|
|
||||||
# HID parameters
|
# HID parameters
|
||||||
self.pointing_device = PointingDevice()
|
|
||||||
self.polling_interval = 20
|
self.polling_interval = 20
|
||||||
self.last_tick = ticks_ms()
|
self.last_tick = ticks_ms()
|
||||||
|
|
||||||
@@ -82,12 +81,8 @@ class Easypoint(Module):
|
|||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# Set the X/Y from easypoint
|
# Set the X/Y from easypoint
|
||||||
self.pointing_device.report_x[0] = x
|
AX.X.move(keyboard, x)
|
||||||
self.pointing_device.report_y[0] = y
|
AX.Y.move(keyboard, y)
|
||||||
|
|
||||||
self.pointing_device.hid_pending = x != 0 or y != 0
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
@@ -96,9 +91,6 @@ class Easypoint(Module):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
if self.pointing_device.hid_pending:
|
|
||||||
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
|
||||||
self._clear_pending_hid()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_powersave_enable(self, keyboard):
|
def on_powersave_enable(self, keyboard):
|
||||||
@@ -107,13 +99,6 @@ class Easypoint(Module):
|
|||||||
def on_powersave_disable(self, keyboard):
|
def on_powersave_disable(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _clear_pending_hid(self):
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
self.pointing_device.report_x[0] = 0
|
|
||||||
self.pointing_device.report_y[0] = 0
|
|
||||||
self.pointing_device.report_w[0] = 0
|
|
||||||
self.pointing_device.button_status[0] = 0
|
|
||||||
|
|
||||||
def _read_raw_state(self):
|
def _read_raw_state(self):
|
||||||
'''Read data from AS5013'''
|
'''Read data from AS5013'''
|
||||||
x, y = self._i2c_rdwr([X], length=2)
|
x, y = self._i2c_rdwr([X], length=2)
|
||||||
|
@@ -46,7 +46,9 @@ class Layers(HoldTap):
|
|||||||
on_release=self._mo_released,
|
on_release=self._mo_released,
|
||||||
)
|
)
|
||||||
make_argumented_key(
|
make_argumented_key(
|
||||||
validator=layer_key_validator, names=('DF',), on_press=self._df_pressed
|
validator=layer_key_validator,
|
||||||
|
names=('DF',),
|
||||||
|
on_press=self._df_pressed,
|
||||||
)
|
)
|
||||||
make_argumented_key(
|
make_argumented_key(
|
||||||
validator=layer_key_validator,
|
validator=layer_key_validator,
|
||||||
@@ -55,10 +57,14 @@ class Layers(HoldTap):
|
|||||||
on_release=self._lm_released,
|
on_release=self._lm_released,
|
||||||
)
|
)
|
||||||
make_argumented_key(
|
make_argumented_key(
|
||||||
validator=layer_key_validator, names=('TG',), on_press=self._tg_pressed
|
validator=layer_key_validator,
|
||||||
|
names=('TG',),
|
||||||
|
on_press=self._tg_pressed,
|
||||||
)
|
)
|
||||||
make_argumented_key(
|
make_argumented_key(
|
||||||
validator=layer_key_validator, names=('TO',), on_press=self._to_pressed
|
validator=layer_key_validator,
|
||||||
|
names=('TO',),
|
||||||
|
on_press=self._to_pressed,
|
||||||
)
|
)
|
||||||
make_argumented_key(
|
make_argumented_key(
|
||||||
validator=layer_key_validator_lt,
|
validator=layer_key_validator_lt,
|
||||||
@@ -108,17 +114,15 @@ class Layers(HoldTap):
|
|||||||
'''
|
'''
|
||||||
As MO(layer) but with mod active
|
As MO(layer) but with mod active
|
||||||
'''
|
'''
|
||||||
keyboard.hid_pending = True
|
|
||||||
# Sets the timer start and acts like MO otherwise
|
# Sets the timer start and acts like MO otherwise
|
||||||
keyboard.keys_pressed.add(key.meta.kc)
|
keyboard.add_key(key.meta.kc)
|
||||||
self._mo_pressed(key, keyboard, *args, **kwargs)
|
self._mo_pressed(key, keyboard, *args, **kwargs)
|
||||||
|
|
||||||
def _lm_released(self, key, keyboard, *args, **kwargs):
|
def _lm_released(self, key, keyboard, *args, **kwargs):
|
||||||
'''
|
'''
|
||||||
As MO(layer) but with mod active
|
As MO(layer) but with mod active
|
||||||
'''
|
'''
|
||||||
keyboard.hid_pending = True
|
keyboard.remove_key(key.meta.kc)
|
||||||
keyboard.keys_pressed.discard(key.meta.kc)
|
|
||||||
self._mo_released(key, keyboard, *args, **kwargs)
|
self._mo_released(key, keyboard, *args, **kwargs)
|
||||||
|
|
||||||
def _tg_pressed(self, key, keyboard, *args, **kwargs):
|
def _tg_pressed(self, key, keyboard, *args, **kwargs):
|
||||||
|
@@ -1,54 +1,40 @@
|
|||||||
from supervisor import ticks_ms
|
from kmk.keys import AX, make_key, make_mouse_key
|
||||||
|
from kmk.kmktime import PeriodicTimer
|
||||||
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
|
|
||||||
from kmk.keys import make_key
|
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
|
|
||||||
|
|
||||||
class PointingDevice:
|
|
||||||
MB_LMB = 1
|
|
||||||
MB_RMB = 2
|
|
||||||
MB_MMB = 4
|
|
||||||
_evt = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.key_states = {}
|
|
||||||
self.hid_pending = False
|
|
||||||
self.report_device = memoryview(self._evt)[0:1]
|
|
||||||
self.report_device[0] = HIDReportTypes.MOUSE
|
|
||||||
self.button_status = memoryview(self._evt)[1:2]
|
|
||||||
self.report_x = memoryview(self._evt)[2:3]
|
|
||||||
self.report_y = memoryview(self._evt)[3:4]
|
|
||||||
self.report_w = memoryview(self._evt)[4:]
|
|
||||||
|
|
||||||
|
|
||||||
class MouseKeys(Module):
|
class MouseKeys(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pointing_device = PointingDevice()
|
|
||||||
self._nav_key_activated = 0
|
self._nav_key_activated = 0
|
||||||
self._up_activated = False
|
self._up_activated = False
|
||||||
self._down_activated = False
|
self._down_activated = False
|
||||||
self._left_activated = False
|
self._left_activated = False
|
||||||
self._right_activated = False
|
self._right_activated = False
|
||||||
|
self._mw_up_activated = False
|
||||||
|
self._mw_down_activated = False
|
||||||
self.max_speed = 10
|
self.max_speed = 10
|
||||||
self.ac_interval = 100 # Delta ms to apply acceleration
|
self.acc_interval = 10 # Delta ms to apply acceleration
|
||||||
self._next_interval = 0 # Time for next tick interval
|
|
||||||
self.move_step = 1
|
self.move_step = 1
|
||||||
|
|
||||||
make_key(
|
make_mouse_key(
|
||||||
names=('MB_LMB',),
|
names=('MB_LMB',),
|
||||||
on_press=self._mb_lmb_press,
|
code=1,
|
||||||
on_release=self._mb_lmb_release,
|
|
||||||
)
|
)
|
||||||
make_key(
|
make_mouse_key(
|
||||||
names=('MB_MMB',),
|
names=('MB_MMB',),
|
||||||
on_press=self._mb_mmb_press,
|
code=4,
|
||||||
on_release=self._mb_mmb_release,
|
|
||||||
)
|
)
|
||||||
make_key(
|
make_mouse_key(
|
||||||
names=('MB_RMB',),
|
names=('MB_RMB',),
|
||||||
on_press=self._mb_rmb_press,
|
code=2,
|
||||||
on_release=self._mb_rmb_release,
|
)
|
||||||
|
make_mouse_key(
|
||||||
|
names=('MB_BTN4',),
|
||||||
|
code=8,
|
||||||
|
)
|
||||||
|
make_mouse_key(
|
||||||
|
names=('MB_BTN5',),
|
||||||
|
code=16,
|
||||||
)
|
)
|
||||||
make_key(
|
make_key(
|
||||||
names=('MW_UP',),
|
names=('MW_UP',),
|
||||||
@@ -94,38 +80,33 @@ class MouseKeys(Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def during_bootup(self, keyboard):
|
def during_bootup(self, keyboard):
|
||||||
return
|
self._timer = PeriodicTimer(self.acc_interval)
|
||||||
|
|
||||||
def matrix_detected_press(self, keyboard):
|
|
||||||
return keyboard.matrix_update is None
|
|
||||||
|
|
||||||
def before_matrix_scan(self, keyboard):
|
def before_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
|
if not self._timer.tick():
|
||||||
|
return
|
||||||
|
|
||||||
if self._nav_key_activated:
|
if self._nav_key_activated:
|
||||||
if self._next_interval <= ticks_ms():
|
|
||||||
# print("hello: ")
|
|
||||||
# print(ticks_ms())
|
|
||||||
self._next_interval = ticks_ms() + self.ac_interval
|
|
||||||
# print(self._next_interval)
|
|
||||||
if self.move_step < self.max_speed:
|
if self.move_step < self.max_speed:
|
||||||
self.move_step = self.move_step + 1
|
self.move_step = self.move_step + 1
|
||||||
if self._right_activated:
|
if self._right_activated:
|
||||||
self.pointing_device.report_x[0] = self.move_step
|
AX.X.move(keyboard, self.move_step)
|
||||||
if self._left_activated:
|
if self._left_activated:
|
||||||
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
|
AX.X.move(keyboard, -self.move_step)
|
||||||
if self._up_activated:
|
if self._up_activated:
|
||||||
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
|
AX.Y.move(keyboard, -self.move_step)
|
||||||
if self._down_activated:
|
if self._down_activated:
|
||||||
self.pointing_device.report_y[0] = self.move_step
|
AX.Y.move(keyboard, self.move_step)
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
return
|
if self._mw_up_activated:
|
||||||
|
AX.W.move(keyboard, 1)
|
||||||
|
if self._mw_down_activated:
|
||||||
|
AX.W.move(keyboard, -1)
|
||||||
|
|
||||||
def before_hid_send(self, keyboard):
|
def before_hid_send(self, keyboard):
|
||||||
if self.pointing_device.hid_pending and keyboard._hid_send_enabled:
|
|
||||||
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
@@ -137,50 +118,21 @@ class MouseKeys(Module):
|
|||||||
def on_powersave_disable(self, keyboard):
|
def on_powersave_disable(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _mb_lmb_press(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] |= self.pointing_device.MB_LMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mb_lmb_release(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_LMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mb_mmb_press(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] |= self.pointing_device.MB_MMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mb_mmb_release(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_MMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mb_rmb_press(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] |= self.pointing_device.MB_RMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mb_rmb_release(self, key, keyboard, *args, **kwargs):
|
|
||||||
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_RMB
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mw_up_press(self, key, keyboard, *args, **kwargs):
|
def _mw_up_press(self, key, keyboard, *args, **kwargs):
|
||||||
self.pointing_device.report_w[0] = self.move_step
|
self._mw_up_activated = True
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mw_up_release(self, key, keyboard, *args, **kwargs):
|
def _mw_up_release(self, key, keyboard, *args, **kwargs):
|
||||||
self.pointing_device.report_w[0] = 0
|
self._mw_up_activated = False
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mw_down_press(self, key, keyboard, *args, **kwargs):
|
def _mw_down_press(self, key, keyboard, *args, **kwargs):
|
||||||
self.pointing_device.report_w[0] = 0xFF
|
self._mw_down_activated = True
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _mw_down_release(self, key, keyboard, *args, **kwargs):
|
def _mw_down_release(self, key, keyboard, *args, **kwargs):
|
||||||
self.pointing_device.report_w[0] = 0
|
self._mw_down_activated = False
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
# Mouse movement
|
# Mouse movement
|
||||||
def _reset_next_interval(self):
|
def _reset_next_interval(self):
|
||||||
if self._nav_key_activated == 1:
|
if self._nav_key_activated == 1:
|
||||||
self._next_interval = ticks_ms() + self.ac_interval
|
|
||||||
self.move_step = 1
|
self.move_step = 1
|
||||||
|
|
||||||
def _check_last(self):
|
def _check_last(self):
|
||||||
@@ -191,56 +143,38 @@ class MouseKeys(Module):
|
|||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._up_activated = True
|
self._up_activated = True
|
||||||
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _ms_up_release(self, key, keyboard, *args, **kwargs):
|
def _ms_up_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._up_activated = False
|
self._up_activated = False
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._check_last()
|
self._check_last()
|
||||||
self.pointing_device.report_y[0] = 0
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
|
|
||||||
def _ms_down_press(self, key, keyboard, *args, **kwargs):
|
def _ms_down_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._down_activated = True
|
self._down_activated = True
|
||||||
# if not self.x_activated and not self.y_activated:
|
|
||||||
# self.next_interval = ticks_ms() + self.ac_intervalle
|
|
||||||
self.pointing_device.report_y[0] = self.move_step
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _ms_down_release(self, key, keyboard, *args, **kwargs):
|
def _ms_down_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._down_activated = False
|
self._down_activated = False
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._check_last()
|
self._check_last()
|
||||||
self.pointing_device.report_y[0] = 0
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
|
|
||||||
def _ms_left_press(self, key, keyboard, *args, **kwargs):
|
def _ms_left_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._left_activated = True
|
self._left_activated = True
|
||||||
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _ms_left_release(self, key, keyboard, *args, **kwargs):
|
def _ms_left_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._left_activated = False
|
self._left_activated = False
|
||||||
self._check_last()
|
self._check_last()
|
||||||
self.pointing_device.report_x[0] = 0
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
|
|
||||||
def _ms_right_press(self, key, keyboard, *args, **kwargs):
|
def _ms_right_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._right_activated = True
|
self._right_activated = True
|
||||||
self.pointing_device.report_x[0] = self.move_step
|
|
||||||
self.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
def _ms_right_release(self, key, keyboard, *args, **kwargs):
|
def _ms_right_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._right_activated = False
|
self._right_activated = False
|
||||||
self._check_last()
|
self._check_last()
|
||||||
self.pointing_device.report_x[0] = 0
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
|
@@ -6,46 +6,48 @@ from micropython import const
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
|
from adafruit_pixelbuf import PixelBuf
|
||||||
|
|
||||||
from kmk.keys import make_argumented_key, make_key
|
from kmk.keys import AX, KC, make_argumented_key, make_key
|
||||||
from kmk.kmktime import PeriodicTimer
|
from kmk.kmktime import PeriodicTimer
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
from kmk.modules.mouse_keys import PointingDevice
|
from kmk.utils import Debug
|
||||||
|
|
||||||
I2C_ADDRESS = 0x0A
|
_I2C_ADDRESS = const(0x0A)
|
||||||
I2C_ADDRESS_ALTERNATIVE = 0x0B
|
_I2C_ADDRESS_ALTERNATIVE = const(0x0B)
|
||||||
|
|
||||||
CHIP_ID = 0xBA11
|
_CHIP_ID = const(0xBA11)
|
||||||
VERSION = 1
|
_VERSION = const(1)
|
||||||
|
|
||||||
REG_LED_RED = 0x00
|
_REG_LED_RED = const(0x00)
|
||||||
REG_LED_GRN = 0x01
|
_REG_LED_GRN = const(0x01)
|
||||||
REG_LED_BLU = 0x02
|
_REG_LED_BLU = const(0x02)
|
||||||
REG_LED_WHT = 0x03
|
_REG_LED_WHT = const(0x03)
|
||||||
|
|
||||||
REG_LEFT = 0x04
|
_REG_LEFT = const(0x04)
|
||||||
REG_RIGHT = 0x05
|
_REG_RIGHT = const(0x05)
|
||||||
REG_UP = 0x06
|
_REG_UP = const(0x06)
|
||||||
REG_DOWN = 0x07
|
_REG_DOWN = const(0x07)
|
||||||
REG_SWITCH = 0x08
|
_REG_SWITCH = const(0x08)
|
||||||
MSK_SWITCH_STATE = 0b10000000
|
_MSK_SWITCH_STATE = const(0b10000000)
|
||||||
|
|
||||||
REG_USER_FLASH = 0xD0
|
_REG_USER_FLASH = const(0xD0)
|
||||||
REG_FLASH_PAGE = 0xF0
|
_REG_FLASH_PAGE = const(0xF0)
|
||||||
REG_INT = 0xF9
|
_REG_INT = const(0xF9)
|
||||||
MSK_INT_TRIGGERED = 0b00000001
|
_MSK_INT_TRIGGERED = const(0b00000001)
|
||||||
MSK_INT_OUT_EN = 0b00000010
|
_MSK_INT_OUT_EN = const(0b00000010)
|
||||||
REG_CHIP_ID_L = 0xFA
|
_REG_CHIP_ID_L = const(0xFA)
|
||||||
RED_CHIP_ID_H = 0xFB
|
_REG_CHIP_ID_H = const(0xFB)
|
||||||
REG_VERSION = 0xFC
|
_REG_VERSION = const(0xFC)
|
||||||
REG_I2C_ADDR = 0xFD
|
_REG_I2C_ADDR = const(0xFD)
|
||||||
REG_CTRL = 0xFE
|
_REG_CTRL = const(0xFE)
|
||||||
MSK_CTRL_SLEEP = 0b00000001
|
_MSK_CTRL_SLEEP = const(0b00000001)
|
||||||
MSK_CTRL_RESET = 0b00000010
|
_MSK_CTRL_RESET = const(0b00000010)
|
||||||
MSK_CTRL_FREAD = 0b00000100
|
_MSK_CTRL_FREAD = const(0b00000100)
|
||||||
MSK_CTRL_FWRITE = 0b00001000
|
_MSK_CTRL_FWRITE = const(0b00001000)
|
||||||
|
|
||||||
ANGLE_OFFSET = 0
|
|
||||||
|
debug = Debug(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TrackballHandlerKeyMeta:
|
class TrackballHandlerKeyMeta:
|
||||||
@@ -78,31 +80,13 @@ class TrackballHandler:
|
|||||||
|
|
||||||
class PointingHandler(TrackballHandler):
|
class PointingHandler(TrackballHandler):
|
||||||
def handle(self, keyboard, trackball, x, y, switch, state):
|
def handle(self, keyboard, trackball, x, y, switch, state):
|
||||||
if x > 0:
|
if x:
|
||||||
trackball.pointing_device.report_x[0] = x
|
AX.X.move(keyboard, x)
|
||||||
elif x < 0:
|
if y:
|
||||||
trackball.pointing_device.report_x[0] = 0xFF & x
|
AX.Y.move(keyboard, y)
|
||||||
if y > 0:
|
|
||||||
trackball.pointing_device.report_y[0] = y
|
|
||||||
elif y < 0:
|
|
||||||
trackball.pointing_device.report_y[0] = 0xFF & y
|
|
||||||
|
|
||||||
if x != 0 or y != 0:
|
if switch == 1: # Button changed state
|
||||||
trackball.pointing_device.hid_pending = True
|
keyboard.pre_process_key(KC.MB_LMB, is_pressed=state)
|
||||||
|
|
||||||
if switch == 1: # Button pressed
|
|
||||||
trackball.pointing_device.button_status[
|
|
||||||
0
|
|
||||||
] |= trackball.pointing_device.MB_LMB
|
|
||||||
trackball.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
if not state and trackball.previous_state is True: # Button released
|
|
||||||
trackball.pointing_device.button_status[
|
|
||||||
0
|
|
||||||
] &= ~trackball.pointing_device.MB_LMB
|
|
||||||
trackball.pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
trackball.previous_state = state
|
|
||||||
|
|
||||||
|
|
||||||
class ScrollHandler(TrackballHandler):
|
class ScrollHandler(TrackballHandler):
|
||||||
@@ -114,19 +98,10 @@ class ScrollHandler(TrackballHandler):
|
|||||||
y = -y
|
y = -y
|
||||||
|
|
||||||
if y != 0:
|
if y != 0:
|
||||||
pointing_device = trackball.pointing_device
|
AX.W.move(keyboard, y)
|
||||||
pointing_device.report_w[0] = 0xFF & y
|
|
||||||
pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
if switch == 1: # Button pressed
|
if switch == 1: # Button changed state
|
||||||
pointing_device.button_status[0] |= pointing_device.MB_LMB
|
keyboard.pre_process_key(KC.MB_LMB, is_pressed=state)
|
||||||
pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
if not state and trackball.previous_state is True: # Button released
|
|
||||||
pointing_device.button_status[0] &= ~pointing_device.MB_LMB
|
|
||||||
pointing_device.hid_pending = True
|
|
||||||
|
|
||||||
trackball.previous_state = state
|
|
||||||
|
|
||||||
|
|
||||||
class KeyHandler(TrackballHandler):
|
class KeyHandler(TrackballHandler):
|
||||||
@@ -173,8 +148,8 @@ class Trackball(Module):
|
|||||||
self,
|
self,
|
||||||
i2c,
|
i2c,
|
||||||
mode=TrackballMode.MOUSE_MODE,
|
mode=TrackballMode.MOUSE_MODE,
|
||||||
address=I2C_ADDRESS,
|
address=_I2C_ADDRESS,
|
||||||
angle_offset=ANGLE_OFFSET,
|
angle_offset=0,
|
||||||
handlers=None,
|
handlers=None,
|
||||||
):
|
):
|
||||||
self.angle_offset = angle_offset
|
self.angle_offset = angle_offset
|
||||||
@@ -185,19 +160,11 @@ class Trackball(Module):
|
|||||||
self._i2c_address = address
|
self._i2c_address = address
|
||||||
self._i2c_bus = i2c
|
self._i2c_bus = i2c
|
||||||
|
|
||||||
self.pointing_device = PointingDevice()
|
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.previous_state = False # click state
|
|
||||||
self.handlers = handlers
|
self.handlers = handlers
|
||||||
self.current_handler = self.handlers[0]
|
self.current_handler = self.handlers[0]
|
||||||
self.polling_interval = 20
|
self.polling_interval = 20
|
||||||
|
|
||||||
chip_id = struct.unpack('<H', bytearray(self._i2c_rdwr([REG_CHIP_ID_L], 2)))[0]
|
|
||||||
if chip_id != CHIP_ID:
|
|
||||||
raise RuntimeError(
|
|
||||||
f'Invalid chip ID: 0x{chip_id:04X}, expected 0x{CHIP_ID:04X}'
|
|
||||||
)
|
|
||||||
|
|
||||||
make_key(
|
make_key(
|
||||||
names=('TB_MODE', 'TB_NEXT_HANDLER', 'TB_N'),
|
names=('TB_MODE', 'TB_NEXT_HANDLER', 'TB_N'),
|
||||||
on_press=self._tb_handler_next_press,
|
on_press=self._tb_handler_next_press,
|
||||||
@@ -210,8 +177,17 @@ class Trackball(Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def during_bootup(self, keyboard):
|
def during_bootup(self, keyboard):
|
||||||
|
chip_id = struct.unpack('<H', bytearray(self._i2c_rdwr([_REG_CHIP_ID_L], 2)))[0]
|
||||||
|
if chip_id != _CHIP_ID:
|
||||||
|
raise RuntimeError(
|
||||||
|
f'Invalid chip ID: 0x{chip_id:04X}, expected 0x{_CHIP_ID:04X}'
|
||||||
|
)
|
||||||
|
|
||||||
self._timer = PeriodicTimer(self.polling_interval)
|
self._timer = PeriodicTimer(self.polling_interval)
|
||||||
|
|
||||||
|
a = math.pi * self.angle_offset / 180
|
||||||
|
self.rot = [[math.cos(a), math.sin(a)], [-math.sin(a), math.cos(a)]]
|
||||||
|
|
||||||
def before_matrix_scan(self, keyboard):
|
def before_matrix_scan(self, keyboard):
|
||||||
'''
|
'''
|
||||||
Return value will be injected as an extra matrix update
|
Return value will be injected as an extra matrix update
|
||||||
@@ -219,14 +195,15 @@ class Trackball(Module):
|
|||||||
if not self._timer.tick():
|
if not self._timer.tick():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not (self._i2c_rdwr([_REG_INT], 1)[0] & _MSK_INT_TRIGGERED):
|
||||||
|
return
|
||||||
|
|
||||||
up, down, left, right, switch, state = self._read_raw_state()
|
up, down, left, right, switch, state = self._read_raw_state()
|
||||||
|
|
||||||
x, y = self._calculate_movement(right - left, down - up)
|
x, y = self._calculate_movement(right - left, down - up)
|
||||||
|
|
||||||
self.current_handler.handle(keyboard, self, x, y, switch, state)
|
self.current_handler.handle(keyboard, self, x, y, switch, state)
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -234,9 +211,6 @@ class Trackball(Module):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
if self.pointing_device.hid_pending:
|
|
||||||
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
|
||||||
self._clear_pending_hid()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_powersave_enable(self, keyboard):
|
def on_powersave_enable(self, keyboard):
|
||||||
@@ -247,23 +221,23 @@ class Trackball(Module):
|
|||||||
|
|
||||||
def set_rgbw(self, r, g, b, w):
|
def set_rgbw(self, r, g, b, w):
|
||||||
'''Set all LED brightness as RGBW.'''
|
'''Set all LED brightness as RGBW.'''
|
||||||
self._i2c_rdwr([REG_LED_RED, r, g, b, w])
|
self._i2c_rdwr([_REG_LED_RED, r, g, b, w])
|
||||||
|
|
||||||
def set_red(self, value):
|
def set_red(self, value):
|
||||||
'''Set brightness of trackball red LED.'''
|
'''Set brightness of trackball red LED.'''
|
||||||
self._i2c_rdwr([REG_LED_RED, value & 0xFF])
|
self._i2c_rdwr([_REG_LED_RED, value & 0xFF])
|
||||||
|
|
||||||
def set_green(self, value):
|
def set_green(self, value):
|
||||||
'''Set brightness of trackball green LED.'''
|
'''Set brightness of trackball green LED.'''
|
||||||
self._i2c_rdwr([REG_LED_GRN, value & 0xFF])
|
self._i2c_rdwr([_REG_LED_GRN, value & 0xFF])
|
||||||
|
|
||||||
def set_blue(self, value):
|
def set_blue(self, value):
|
||||||
'''Set brightness of trackball blue LED.'''
|
'''Set brightness of trackball blue LED.'''
|
||||||
self._i2c_rdwr([REG_LED_BLU, value & 0xFF])
|
self._i2c_rdwr([_REG_LED_BLU, value & 0xFF])
|
||||||
|
|
||||||
def set_white(self, value):
|
def set_white(self, value):
|
||||||
'''Set brightness of trackball white LED.'''
|
'''Set brightness of trackball white LED.'''
|
||||||
self._i2c_rdwr([REG_LED_WHT, value & 0xFF])
|
self._i2c_rdwr([_REG_LED_WHT, value & 0xFF])
|
||||||
|
|
||||||
def activate_handler(self, handler):
|
def activate_handler(self, handler):
|
||||||
if isinstance(handler, TrackballHandler):
|
if isinstance(handler, TrackballHandler):
|
||||||
@@ -272,7 +246,8 @@ class Trackball(Module):
|
|||||||
try:
|
try:
|
||||||
self.current_handler = self.handlers[handler]
|
self.current_handler = self.handlers[handler]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print(f'no handler found with id {handler}')
|
if debug.enabled:
|
||||||
|
debug(f'no handler found with id {handler}')
|
||||||
|
|
||||||
def next_handler(self):
|
def next_handler(self):
|
||||||
next_index = self.handlers.index(self.current_handler) + 1
|
next_index = self.handlers.index(self.current_handler) + 1
|
||||||
@@ -280,26 +255,19 @@ class Trackball(Module):
|
|||||||
next_index = 0
|
next_index = 0
|
||||||
self.activate_handler(next_index)
|
self.activate_handler(next_index)
|
||||||
|
|
||||||
def _clear_pending_hid(self):
|
|
||||||
self.pointing_device.hid_pending = False
|
|
||||||
self.pointing_device.report_x[0] = 0
|
|
||||||
self.pointing_device.report_y[0] = 0
|
|
||||||
self.pointing_device.report_w[0] = 0
|
|
||||||
self.pointing_device.button_status[0] = 0
|
|
||||||
|
|
||||||
def _read_raw_state(self):
|
def _read_raw_state(self):
|
||||||
'''Read up, down, left, right and switch data from trackball.'''
|
'''Read up, down, left, right and switch data from trackball.'''
|
||||||
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)
|
left, right, up, down, switch = self._i2c_rdwr([_REG_LEFT], 5)
|
||||||
switch, switch_state = (
|
switch_changed, switch_state = (
|
||||||
switch & ~MSK_SWITCH_STATE,
|
switch & ~_MSK_SWITCH_STATE,
|
||||||
(switch & MSK_SWITCH_STATE) > 0,
|
(switch & _MSK_SWITCH_STATE) > 0,
|
||||||
)
|
)
|
||||||
return up, down, left, right, switch, switch_state
|
return up, down, left, right, switch_changed, switch_state
|
||||||
|
|
||||||
def _i2c_rdwr(self, data, length=0):
|
def _i2c_rdwr(self, data, length=0):
|
||||||
'''Write and optionally read I2C data.'''
|
'''Write and optionally read I2C data.'''
|
||||||
while not self._i2c_bus.try_lock():
|
if not self._i2c_bus.try_lock():
|
||||||
pass
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if length > 0:
|
if length > 0:
|
||||||
@@ -327,17 +295,24 @@ class Trackball(Module):
|
|||||||
if raw_x == 0 and raw_y == 0:
|
if raw_x == 0 and raw_y == 0:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
||||||
var_accel = 1
|
scale = math.sqrt(raw_x**2 + raw_y**2)
|
||||||
power = 2.5
|
x = (self.rot[0][0] * raw_x + self.rot[0][1] * raw_y) * scale
|
||||||
|
y = (self.rot[1][0] * raw_x + self.rot[1][1] * raw_y) * scale
|
||||||
|
|
||||||
angle_rad = math.atan2(raw_y, raw_x) + self.angle_offset
|
return int(x), int(y)
|
||||||
vector_length = math.sqrt(pow(raw_x, 2) + pow(raw_y, 2))
|
|
||||||
vector_length = pow(vector_length * var_accel, power)
|
|
||||||
x = math.floor(vector_length * math.cos(angle_rad))
|
|
||||||
y = math.floor(vector_length * math.sin(angle_rad))
|
|
||||||
|
|
||||||
limit = 127 # hid size limit
|
|
||||||
x_clamped = max(min(limit, x), -limit)
|
|
||||||
y_clamped = max(min(limit, y), -limit)
|
|
||||||
|
|
||||||
return x_clamped, y_clamped
|
class TrackballPixel(PixelBuf):
|
||||||
|
'''PixelBuf interface for the Trackball RGBW LED'''
|
||||||
|
|
||||||
|
def __init__(self, trackball, **kwargs):
|
||||||
|
self.trackball = trackball
|
||||||
|
kwargs['byteorder'] = 'RGBW'
|
||||||
|
super().__init__(1, **kwargs)
|
||||||
|
|
||||||
|
def deinit(self):
|
||||||
|
super().deinit()
|
||||||
|
self.trackball.set_rgbw(0, 0, 0, 0)
|
||||||
|
|
||||||
|
def _transmit(self, b):
|
||||||
|
self.trackball.set_rgbw(b[0], b[1], b[2], b[3])
|
||||||
|
@@ -23,6 +23,7 @@ per-file-ignores =
|
|||||||
# your imports in whatever order you want
|
# your imports in whatever order you want
|
||||||
user_keymaps/**/*.py: E131,F401,E501,E241,E131,BLK100,I003
|
user_keymaps/**/*.py: E131,F401,E501,E241,E131,BLK100,I003
|
||||||
boards/**/main.py: E131,F401,E501,E241,E131,BLK100,I003
|
boards/**/main.py: E131,F401,E501,E241,E131,BLK100,I003
|
||||||
|
boards/**/kb.py: E131,F401,E501,E241,E131,BLK100,I003
|
||||||
tests/test_data/keymaps/**/*.py: F401,E501
|
tests/test_data/keymaps/**/*.py: F401,E501
|
||||||
|
|
||||||
[isort]
|
[isort]
|
||||||
|
Reference in New Issue
Block a user