diff --git a/.circleci/config.yml b/.circleci/config.yml
index a84d61b..c1958b5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,26 +1,24 @@
+---
version: 2
jobs:
- test:
+ build:
docker:
- image: 'kmkfw/base'
environment:
- KMK_TEST: 1
- PIPENV_VENV_IN_PROJECT: 1
+ KMK_TEST: 1
steps:
- checkout
- - restore_cache:
- keys:
- - v2-kmk-venv-{{ checksum "Pipfile.lock" }}
-
- run: make test
+ - run: make dist
+ - run: make dist-deploy
workflows:
version: 2
build-deploy:
jobs:
- - test:
+ - build:
filters:
branches:
only: /.*/
diff --git a/.gitignore b/.gitignore
index 6292408..c4944b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,6 +102,7 @@ venv.bak/
# mypy
.mypy_cache/
+.compiled/
.ampy
.submodules
@@ -119,3 +120,8 @@ venv.bak/
# Mountpoints
mnt/
mnt2/
+
+# build artifacts
+kmk/release_info.py
+kmk/release_info.mpy
+*.mpy
diff --git a/.s3cfg b/.s3cfg
new file mode 100644
index 0000000..4ae2654
--- /dev/null
+++ b/.s3cfg
@@ -0,0 +1,81 @@
+[default]
+access_key =
+access_token =
+add_encoding_exts =
+add_headers =
+bucket_location = US
+ca_certs_file =
+cache_file =
+check_ssl_certificate = True
+check_ssl_hostname = True
+cloudfront_host = cloudfront.amazonaws.com
+content_disposition =
+content_type =
+default_mime_type = binary/octet-stream
+delay_updates = False
+delete_after = False
+delete_after_fetch = False
+delete_removed = False
+dry_run = False
+enable_multipart = True
+encoding = UTF-8
+encrypt = False
+expiry_date =
+expiry_days =
+expiry_prefix =
+follow_symlinks = False
+force = False
+get_continue = False
+gpg_command = /usr/bin/gpg
+gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
+gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
+gpg_passphrase =
+guess_mime_type = True
+host_base = sfo2.digitaloceanspaces.com
+host_bucket = %(bucket)s.sfo2.digitaloceanspaces.com
+human_readable_sizes = False
+invalidate_default_index_on_cf = False
+invalidate_default_index_root_on_cf = True
+invalidate_on_cf = False
+kms_key =
+limit = -1
+limitrate = 0
+list_md5 = False
+log_target_prefix =
+long_listing = False
+max_delete = -1
+mime_type =
+multipart_chunk_size_mb = 15
+multipart_max_chunks = 10000
+preserve_attrs = True
+progress_meter = True
+proxy_host =
+proxy_port = 0
+put_continue = False
+recursive = False
+recv_chunk = 65536
+reduced_redundancy = False
+requester_pays = False
+restore_days = 1
+restore_priority = Standard
+secret_key =
+send_chunk = 65536
+server_side_encryption = False
+signature_v2 = False
+signurl_use_https = False
+simpledb_host = sdb.amazonaws.com
+skip_existing = False
+socket_timeout = 300
+stats = False
+stop_on_error = False
+storage_class =
+throttle_max = 100
+upload_id =
+urlencoding_mode = normal
+use_http_expect = False
+use_https = True
+use_mime_magic = True
+verbosity = WARNING
+website_endpoint = http://%(bucket)s.s3-website-%(location)s.amazonaws.com/
+website_error =
+website_index = index.html
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..80d094f
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,20 @@
+FROM python:3.7-alpine
+
+RUN mkdir -p /app
+WORKDIR /app
+
+RUN apk update && apk add alpine-sdk coreutils curl gettext git git-lfs openssh rsync wget zip
+
+RUN pip install pipenv
+
+### Get a local copy of CircuitPython and its dependencies
+# Our absolute baseline is 4.0.0, which (as of writing) shares MPY compat
+# with all future versions. Our baseline will need to update as MPY compat
+# changes
+RUN git clone --branch 4.0.0 --depth 1 https://github.com/adafruit/CircuitPython /opt/circuitpython
+RUN git -C /opt/circuitpython submodule update --init
+
+### Build the MPY compiler
+RUN make -C /opt/circuitpython/mpy-cross
+
+ENV PATH=/opt/circuitpython/mpy-cross:${PATH}
diff --git a/Dockerfile_base b/Dockerfile_base
deleted file mode 100644
index 66e3f2e..0000000
--- a/Dockerfile_base
+++ /dev/null
@@ -1,21 +0,0 @@
-# vim: ft=dockerfile
-
-# Not using python:3.7 here because team-gcc-arm-embedded/ppa does not support
-# Ubuntu Cosmic or Debian Stretch, and Alpine, bizarrely, does not seem to
-# package GCC cross compilers
-FROM ubuntu:bionic
-
-# Set up PPAs we'll need for Python and for GCC ARM
-RUN apt-get update && apt-get install -y software-properties-common
-RUN add-apt-repository ppa:deadsnakes/ppa
-RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa
-
-# Install Python
-RUN apt-get update && apt-get install -y python3.7 python3.7-dev build-essential pkg-config libffi-dev curl
-RUN curl https://bootstrap.pypa.io/get-pip.py | python3.7
-# Downgrade pip to work around https://github.com/pypa/pipenv/issues/2924
-RUN python3.7 -m pip install pip==18.0
-RUN python3.7 -m pip install pipenv==2018.7.1
-
-# Install KMK CI and/or build-time dependencies
-RUN apt-get install -y gcc-arm-embedded gettext ssh wget unzip rsync git locales libusb-dev
diff --git a/Makefile b/Makefile
index ddc34ed..3734385 100644
--- a/Makefile
+++ b/Makefile
@@ -6,20 +6,73 @@
.DEFAULT: all
+DIST_DESCRIBE_CMD = git describe --always --abbrev=0 --dirty --broken
+
DOCKER_BASE_TAG ?= latest
DOCKER_TAG ?= latest
AMPY_PORT ?= /dev/ttyUSB0
AMPY_BAUD ?= 115200
AMPY_DELAY ?= 1.5
-ARDUINO ?= /usr/share/arduino
-PIPENV ?= $(shell which pipenv)
+PIPENV ?= $(shell which pipenv 2>/dev/null)
+
+MPY_CROSS ?= $(shell which mpy-cross 2>/dev/null)
+MPY_FLAGS ?= '-O2'
+MPY_SOURCES = 'kmk/'
+MPY_TARGET_DIR ?= .compiled
+PY_KMK_TREE = $(shell find $(MPY_SOURCES) -name "*.py")
+DIST_DESCRIBE = $(shell $(DIST_DESCRIBE_CMD))
all: copy-kmk copy-bootpy copy-keymap
-.docker_base: Dockerfile_base
+compile: $(MPY_TARGET_DIR)/.mpy.compiled
+
+$(MPY_TARGET_DIR)/.mpy.compiled: $(PY_KMK_TREE)
+ifeq ($(MPY_CROSS),)
+ @echo "===> Could not find mpy-cross in PATH, exiting"
+ @false
+endif
+ @echo "===> Compiling all py files to mpy with flags $(MPY_FLAGS)"
+ @mkdir -p $(MPY_TARGET_DIR)
+ @echo "KMK_RELEASE = '$(DIST_DESCRIBE)'" > $(MPY_SOURCES)/release_info.py
+ @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' \;
+ @rm -rf $(MPY_SOURCES)/release_info.py
+ @touch $(MPY_TARGET_DIR)/.mpy.compiled
+
+dist: dist/kmk-latest.zip dist/kmk-latest.unoptimized.zip dist/$(DIST_DESCRIBE).zip dist/$(DIST_DESCRIBE).unoptimized.zip
+
+dist-deploy: devdeps dist
+ @echo "===> Uploading artifacts to https://cdn.kmkfw.io/"
+ @$(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-$(DIST_DESCRIBE).zip dist/kmk-$(DIST_DESCRIBE).unoptimized.zip s3://kmk-releases/ >/dev/null
+ @[[ "$${CIRCLE_BRANCH}" == "master" ]] && echo "====> Uploading artifacts as 'latest' to https://cdn.kmkfw.io/" || true
+ @[[ "$${CIRCLE_BRANCH}" == "master" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.zip dist/kmk-latest.unoptimized.zip s3://kmk-releases/ >/dev/null || true
+ @[[ -n "$${CIRCLE_TAG}" ]] && echo "====> Uploading artifacts as '$${CIRCLE_TAG}' to https://cdn.kmkfw.io/" || true
+ @[[ -n "$${CIRCLE_TAG}" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.zip s3://kmk-releases/$${CIRCLE_TAG}.zip >/dev/null || true
+ @[[ -n "$${CIRCLE_TAG}" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.unoptimized.zip s3://kmk-releases/$${CIRCLE_TAG}.unoptimized.zip >/dev/null || true
+
+dist/kmk-latest.zip: compile
+ @echo "===> Building optimized ZIP"
+ @mkdir -p dist
+ @cd $(MPY_TARGET_DIR) && zip -r ../dist/kmk-latest.zip kmk 2>&1 >/dev/null
+
+dist/$(DIST_DESCRIBE).zip: dist/kmk-latest.zip
+ @echo "===> Aliasing optimized ZIP"
+ @cp dist/kmk-latest.zip dist/kmk-$(DIST_DESCRIBE).zip
+
+dist/kmk-latest.unoptimized.zip: $(PY_KMK_TREE)
+ @echo "===> Building unoptimized ZIP"
+ @mkdir -p dist
+ @echo "KMK_RELEASE = '$(DIST_DESCRIBE)'" > kmk/release_info.py
+ @zip -r dist/kmk-latest.unoptimized.zip kmk 2>&1 >/dev/null
+ @rm -rf kmk/release_info.py
+
+dist/$(DIST_DESCRIBE).unoptimized.zip: dist/kmk-latest.unoptimized.zip
+ @echo "===> Aliasing unoptimized ZIP"
+ @cp dist/kmk-latest.unoptimized.zip dist/kmk-$(DIST_DESCRIBE).unoptimized.zip
+
+.docker_base: Dockerfile
@echo "===> Building Docker base image kmkfw/base:${DOCKER_BASE_TAG}"
- @docker build -f Dockerfile_base -t kmkfw/base:${DOCKER_BASE_TAG} .
+ @docker build -t kmkfw/base:${DOCKER_BASE_TAG} .
@touch .docker_base
docker-base: .docker_base
@@ -30,7 +83,7 @@ docker-base-deploy: docker-base
.devdeps: Pipfile.lock
@echo "===> Installing dependencies with pipenv"
- @$(PIPENV) install --dev --ignore-pipfile
+ @$(PIPENV) sync --dev
@touch .devdeps
devdeps: .devdeps
@@ -41,14 +94,14 @@ lint: devdeps
fix-isort: devdeps
@find kmk/ tests/ user_keymaps/ -name "*.py" | xargs $(PIPENV) run isort
-clean: clean-build-log
+clean:
@echo "===> Cleaning build artifacts"
- @rm -rf .devdeps build
-
-clean-build-log:
- @echo "===> Clearing previous .build.log"
- @rm -rf .build.log
+ @rm -rf .devdeps build dist $(MPY_TARGET_DIR)
+# This is mostly a leftover from the days we vendored stuff from
+# micropython-lib via submodules. Leaving this here mostly in case someone goes
+# exploring through the history of KMK's repo and manages to screw up their
+# repo state (those were glitchy times...)
powerwash: clean
@echo "===> Removing vendor/ to force a re-pull"
@rm -rf vendor
diff --git a/Pipfile b/Pipfile
index bec5f19..e6eb58b 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,19 +4,20 @@ verify_ssl = true
name = "pypi"
[packages]
-pydux = "*"
[dev-packages]
-adafruit-ampy = "*"
"flake8" = "*"
-"flake8-comprehensions" = "*"
-ipython = "*"
-ipdb = "*"
"flake8-commas" = "*"
-isort = "*"
+"flake8-comprehensions" = "*"
"flake8-isort" = "*"
-neovim = "*"
"flake8-per-file-ignores" = "*"
+"python-magic" = "*"
+adafruit-ampy = "*"
+ipdb = "*"
+ipython = "*"
+isort = "*"
+neovim = "*"
+s3cmd = "*"
[requires]
python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
index 7c05b8e..93fb96e 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "96625b372d35c7f5ed0fd3289ba61afd0bcc034ddad31feb958a107e2751fb0a"
+ "sha256": "8f51706fcfb278497a6d3083109744210150dc3c644ead11eda3e3cd806e2e14"
},
"pipfile-spec": 6,
"requires": {
@@ -15,23 +15,15 @@
}
]
},
- "default": {
- "pydux": {
- "hashes": [
- "sha256:5cb9217be9d8c7ff79b028f6f02597bbb055b107ce8eecbe5f631f3fc76d793f",
- "sha256:bed123b5255d566f792b9ceebad87e3f9c1d2d85abed4b9a9475ffc831035879"
- ],
- "index": "pypi",
- "version": "==0.2.2"
- }
- },
+ "default": {},
"develop": {
"adafruit-ampy": {
"hashes": [
- "sha256:1055827874010f48c7dbd3cde4b1d7c6f6732661fad193b188a398e88961fc62"
+ "sha256:46cbb1ebb585c2c01b9d34625dbef618df95c4256a1fc6ac13cb13bbd4a8b6c0",
+ "sha256:cd8d6b831a1c76d712e30e224e3945428f77bb0c6cccbf06239b31aaf4d4e5b7"
],
"index": "pypi",
- "version": "==1.0.5"
+ "version": "==1.0.7"
},
"backcall": {
"hashes": [
@@ -42,25 +34,25 @@
},
"click": {
"hashes": [
- "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
- "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
+ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
+ "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
- "version": "==6.7"
+ "version": "==7.0"
},
"decorator": {
"hashes": [
- "sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82",
- "sha256:c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c"
+ "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
+ "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
],
- "version": "==4.3.0"
+ "version": "==4.4.0"
},
"flake8": {
"hashes": [
- "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0",
- "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37"
+ "sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670",
+ "sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2"
],
"index": "pypi",
- "version": "==3.5.0"
+ "version": "==3.6.0"
},
"flake8-commas": {
"hashes": [
@@ -72,27 +64,27 @@
},
"flake8-comprehensions": {
"hashes": [
- "sha256:b83891fec0e680b07aa1fd92e53eb6993be29a0f3673a09badbe8da307c445e0",
- "sha256:e4ccf1627f75f192eb7fde640f5edb81c98d04b1390df9d4145ffd7710bb1ef2"
+ "sha256:35f826956e87f230415cde9c3b8b454e785736cf5ff0be551c441b41b937f699",
+ "sha256:f0b61d983d608790abf3664830d68efd3412265c2d10f6a4ba1a353274dbeb64"
],
"index": "pypi",
- "version": "==1.4.1"
+ "version": "==2.1.0"
},
"flake8-isort": {
"hashes": [
- "sha256:298d7904ac3a46274edf4ce66fd7e272c2a60c34c3cc999dea000608d64e5e6e",
- "sha256:5992850626ce96547b1f1c7e8a7f0ef49ab2be44eca2177934566437b636fa3c"
+ "sha256:1e67b6b90a9b980ac3ff73782087752d406ce0a729ed928b92797f9fa188917e",
+ "sha256:81a8495eefed3f2f63f26cd2d766c7b1191e923a15b9106e6233724056572c68"
],
"index": "pypi",
- "version": "==2.5"
+ "version": "==2.7.0"
},
"flake8-per-file-ignores": {
"hashes": [
- "sha256:3c4b1d770fa509aaad997ca147bd3533b730c3f6c48290b69a4265072c465522",
- "sha256:4ee4f24cbea5e18e1fefdfccb043e819caf483d16d08e39cb6df5d18b0407275"
+ "sha256:2ee2b61e23cc84e7e76b8f7b2ffc135ec0c3331cba776bb5c03ab5d562b0f40c",
+ "sha256:aeac75cc29425b3b4b73eaa92941939dbe16b83f689381ebaef1471982fdcb47"
],
"index": "pypi",
- "version": "==0.6"
+ "version": "==0.8.1"
},
"greenlet": {
"hashes": [
@@ -120,18 +112,18 @@
},
"ipdb": {
"hashes": [
- "sha256:7081c65ed7bfe7737f83fa4213ca8afd9617b42ff6b3f1daf9a3419839a2a00a"
+ "sha256:dce2112557edfe759742ca2d0fee35c59c97b0cc7a05398b791079d78f1519ce"
],
"index": "pypi",
- "version": "==0.11"
+ "version": "==0.12"
},
"ipython": {
"hashes": [
- "sha256:007dcd929c14631f83daff35df0147ea51d1af420da303fd078343878bd5fb62",
- "sha256:b0f2ef9eada4a68ef63ee10b6dde4f35c840035c50fd24265f8052c98947d5a4"
+ "sha256:11067ab11d98b1e6c7f0993506f7a5f8a91af420f7e82be6575fcb7a6ca372a0",
+ "sha256:60bc55c2c1d287161191cc2469e73c116d9b634cff25fe214a43cba7cec94c79"
],
"index": "pypi",
- "version": "==6.5.0"
+ "version": "==7.6.1"
},
"ipython-genutils": {
"hashes": [
@@ -142,19 +134,18 @@
},
"isort": {
"hashes": [
- "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af",
- "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8",
- "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"
+ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
+ "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
],
"index": "pypi",
- "version": "==4.3.4"
+ "version": "==4.3.21"
},
"jedi": {
"hashes": [
- "sha256:b409ed0f6913a701ed474a614a3bb46e6953639033e31f769ca7581da5bd1ec1",
- "sha256:c254b135fb39ad76e78d4d8f92765ebc9bf92cbc76f49e97ade1d5f5121e1f6f"
+ "sha256:53c850f1a7d3cfcd306cc513e2450a54bdf5cacd7604b74e42dd1f0758eaaf36",
+ "sha256:e07457174ef7cb2342ff94fa56484fe41cec7ef69b0059f01d3f812379cb6f7c"
],
- "version": "==0.12.1"
+ "version": "==0.14.1"
},
"mccabe": {
"hashes": [
@@ -165,37 +156,39 @@
},
"msgpack": {
"hashes": [
- "sha256:0b3b1773d2693c70598585a34ca2715873ba899565f0a7c9a1545baef7e7fbdc",
- "sha256:0bae5d1538c5c6a75642f75a1781f3ac2275d744a92af1a453c150da3446138b",
- "sha256:0ee8c8c85aa651be3aa0cd005b5931769eaa658c948ce79428766f1bd46ae2c3",
- "sha256:1369f9edba9500c7a6489b70fdfac773e925342f4531f1e3d4c20ac3173b1ae0",
- "sha256:22d9c929d1d539f37da3d1b0e16270fa9d46107beab8c0d4d2bddffffe895cee",
- "sha256:2ff43e3247a1e11d544017bb26f580a68306cec7a6257d8818893c1fda665f42",
- "sha256:31a98047355d34d047fcdb55b09cb19f633cf214c705a765bd745456c142130c",
- "sha256:8767eb0032732c3a0da92cbec5ac186ef89a3258c6edca09161472ca0206c45f",
- "sha256:8acc8910218555044e23826980b950e96685dc48124a290c86f6f41a296ea172",
- "sha256:ab189a6365be1860a5ecf8159c248f12d33f79ea799ae9695fa6a29896dcf1d4",
- "sha256:cfd6535feb0f1cf1c7cdb25773e965cc9f92928244a8c3ef6f8f8a8e1f7ae5c4",
- "sha256:e274cd4480d8c76ec467a85a9c6635bbf2258f0649040560382ab58cabb44bcf",
- "sha256:f86642d60dca13e93260187d56c2bef2487aa4d574a669e8ceefcf9f4c26fd00",
- "sha256:f8a57cbda46a94ed0db55b73e6ab0c15e78b4ede8690fa491a0e55128d552bb0",
- "sha256:fcea97a352416afcbccd7af9625159d80704a25c519c251c734527329bb20d0e"
+ "sha256:26cb40116111c232bc235ce131cc3b4e76549088cb154e66a2eb8ff6fcc907ec",
+ "sha256:300fd3f2c664a3bf473d6a952f843b4a71454f4c592ed7e74a36b205c1782d28",
+ "sha256:3129c355342853007de4a2a86e75eab966119733eb15748819b6554363d4e85c",
+ "sha256:31f6d645ee5a97d59d3263fab9e6be76f69fa131cddc0d94091a3c8aca30d67a",
+ "sha256:3ce7ef7ee2546c3903ca8c934d09250531b80c6127e6478781ae31ed835aac4c",
+ "sha256:4008c72f5ef2b7936447dcb83db41d97e9791c83221be13d5e19db0796df1972",
+ "sha256:62bd8e43d204580308d477a157b78d3fee2fb4c15d32578108dc5d89866036c8",
+ "sha256:70cebfe08fb32f83051971264466eadf183101e335d8107b80002e632f425511",
+ "sha256:72cb7cf85e9df5251abd7b61a1af1fb77add15f40fa7328e924a9c0b6bc7a533",
+ "sha256:7c55649965c35eb32c499d17dadfb8f53358b961582846e1bc06f66b9bccc556",
+ "sha256:86b963a5de11336ec26bc4f839327673c9796b398b9f1fe6bb6150c2a5d00f0f",
+ "sha256:8c73c9bcdfb526247c5e4f4f6cf581b9bb86b388df82cfcaffde0a6e7bf3b43a",
+ "sha256:8e68c76c6aff4849089962d25346d6784d38e02baa23ffa513cf46be72e3a540",
+ "sha256:97ac6b867a8f63debc64f44efdc695109d541ecc361ee2dce2c8884ab37360a1",
+ "sha256:9d4f546af72aa001241d74a79caec278bcc007b4bcde4099994732e98012c858",
+ "sha256:a28e69fe5468c9f5251c7e4e7232286d71b7dfadc74f312006ebe984433e9746",
+ "sha256:fd509d4aa95404ce8d86b4e32ce66d5d706fd6646c205e1c2a715d87078683a2"
],
- "version": "==0.5.6"
+ "version": "==0.6.1"
},
"neovim": {
"hashes": [
- "sha256:6ce58a742e0427491c0e1c8108556ee72ba33844209bd9e226b8da9538299276"
+ "sha256:a6a0e7a5b4433bf4e6ddcbc5c5ff44170be7d84259d002b8e8d8fb4ee78af60f"
],
"index": "pypi",
- "version": "==0.2.6"
+ "version": "==0.3.1"
},
"parso": {
"hashes": [
- "sha256:35704a43a3c113cce4de228ddb39aab374b8004f4f2407d070b6a2ca784ce8a2",
- "sha256:895c63e93b94ac1e1690f5fdd40b65f07c8171e3e53cbd7793b5b96c0e0a7f24"
+ "sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc",
+ "sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c"
],
- "version": "==0.3.1"
+ "version": "==0.5.1"
},
"pathmatch": {
"hashes": [
@@ -205,26 +198,26 @@
},
"pexpect": {
"hashes": [
- "sha256:2a8e88259839571d1251d278476f3eec5db26deb73a70be5ed5dc5435e418aba",
- "sha256:3fbd41d4caf27fa4a377bfd16fef87271099463e6fa73e92a52f92dfee5d425b"
+ "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1",
+ "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb"
],
"markers": "sys_platform != 'win32'",
- "version": "==4.6.0"
+ "version": "==4.7.0"
},
"pickleshare": {
"hashes": [
- "sha256:84a9257227dfdd6fe1b4be1319096c20eb85ff1e82c7932f36efccfe1b09737b",
- "sha256:c9a2541f25aeabc070f12f452e1f2a8eae2abd51e1cd19e8430402bdf4c1d8b5"
+ "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca",
+ "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"
],
- "version": "==0.7.4"
+ "version": "==0.7.5"
},
"prompt-toolkit": {
"hashes": [
- "sha256:1df952620eccb399c53ebb359cc7d9a8d3a9538cb34c5a1344bdbeb29fbcc381",
- "sha256:3f473ae040ddaa52b52f97f6b4a493cfa9f5920c255a12dc56a7d34397a398a4",
- "sha256:858588f1983ca497f1cf4ffde01d978a3ea02b01c8a26a8bbc5cd2e66d816917"
+ "sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780",
+ "sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1",
+ "sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"
],
- "version": "==1.0.15"
+ "version": "==2.0.9"
},
"ptyprocess": {
"hashes": [
@@ -235,24 +228,30 @@
},
"pycodestyle": {
"hashes": [
- "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",
- "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9"
+ "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83",
+ "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a"
],
- "version": "==2.3.1"
+ "version": "==2.4.0"
},
"pyflakes": {
"hashes": [
- "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f",
- "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805"
+ "sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49",
+ "sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae"
],
- "version": "==1.6.0"
+ "version": "==2.0.0"
},
"pygments": {
"hashes": [
- "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
- "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
+ "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
+ "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
],
- "version": "==2.2.0"
+ "version": "==2.4.2"
+ },
+ "pynvim": {
+ "hashes": [
+ "sha256:cf6490c4e586c9da01a32f3e0ae21c61342d7ea171e06025bda210bdc95cbe05"
+ ],
+ "version": "==0.3.2"
},
"pyserial": {
"hashes": [
@@ -261,32 +260,49 @@
],
"version": "==3.4"
},
+ "python-dateutil": {
+ "hashes": [
+ "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
+ "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
+ ],
+ "version": "==2.8.0"
+ },
"python-dotenv": {
"hashes": [
- "sha256:122290a38ece9fe4f162dc7c95cae3357b983505830a154d3c98ef7f6c6cea77",
- "sha256:4a205787bc829233de2a823aa328e44fd9996fedb954989a21f1fc67c13d7a77"
+ "sha256:debd928b49dbc2bf68040566f55cdb3252458036464806f4094487244e2a4093",
+ "sha256:f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544"
],
- "version": "==0.9.1"
+ "version": "==0.10.3"
},
- "simplegeneric": {
+ "python-magic": {
"hashes": [
- "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173"
+ "sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375",
+ "sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5"
],
- "version": "==0.8.1"
+ "index": "pypi",
+ "version": "==0.4.15"
+ },
+ "s3cmd": {
+ "hashes": [
+ "sha256:231fe00daedb13095ce38ccf264bbe81d133f6e82f1484ef2f5efdc3f21b9ee8",
+ "sha256:6d7a3a49a12048a6c8e5fbb5ef42a83101e2fc69f16013d292b7f37ecfc574a0"
+ ],
+ "index": "pypi",
+ "version": "==2.0.2"
},
"six": {
"hashes": [
- "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
- "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
],
- "version": "==1.11.0"
+ "version": "==1.12.0"
},
"testfixtures": {
"hashes": [
- "sha256:334497d26344e8c0c5d01b4d785a1c83464573151e6a5f7ab250eb7981d452ec",
- "sha256:53c06c1feb0bf378d63c54d1d96858978422d5a34793b39f0dcb0e44f8ec26f4"
+ "sha256:665a298976c8d77f311b65c46f16b7cda7229a47dff5ad7c822e5b3371a439e2",
+ "sha256:9d230c5c80746f9f86a16a1f751a5cf5d8e317d4cc48243a19fb180d22303bce"
],
- "version": "==6.3.0"
+ "version": "==6.10.0"
},
"traitlets": {
"hashes": [
@@ -297,11 +313,11 @@
},
"typing": {
"hashes": [
- "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d",
- "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4",
- "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"
+ "sha256:38566c558a0a94d6531012c8e917b1b8518a41e418f7f15f00e129cc80162ad3",
+ "sha256:53765ec4f83a2b720214727e319607879fec4acde22c4fbb54fa2604e79e44ce",
+ "sha256:84698954b4e6719e912ef9a42a2431407fe3755590831699debda6fba92aac55"
],
- "version": "==3.6.6"
+ "version": "==3.7.4"
},
"wcwidth": {
"hashes": [
diff --git a/README.md b/README.md
index 8e5b003..8f42fbd 100644
--- a/README.md
+++ b/README.md
@@ -1,99 +1,136 @@
-# KMK: Python-based keyboard firmware for humans (and ARM microcontrollers)
+# KMK: Clackety Keyboards Powered by Python
-[](https://circleci.com/gh/KMKfw/kmk_firmware/tree/master)[](https://cla-assistant.io/KMKfw/kmk_firmware)
+KMK is a feature-rich and beginner-friendly firmware for computer keyboards
+written and configured in
+[CircuitPython](https://github.com/adafruit/circuitpython). **KMK is currently
+in public beta, however should handle almost all workflows without major
+issues**.
-#### [Join our Matrix community for chat and support!](https://matrix.to/#/+kmk:kmkfw.io)
+You can always find the latest releases on our CDN, in [compiled and
+optimized](https://cdn.kmkfw.io/kmk-latest.zip) and [raw, hackable text
+file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip) forms. These follow the
+`master` branch here on GitHub.
-[Or, head directly to the #support channel](https://matrix.to/#/#support:kmkfw.io)
+> If you need support with KMK or just want to say hi, find us in
+> [#general:kmkfw.io on Matrix](https://matrix.to/#/#general:kmkfw.io). Other
+> channels exist in [the same community](https://matrix.to/#/+kmk:kmkfw.io).
+> These channels are bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
+> for convenience.
+>
+> If you ask for help on chat or open a bug report, if possible please give us
+> your commit SHA, found by running `from kmk.consts import KMK_RELEASE;
+> print(KMK_RELEASE)` in the REPL on your controller.
-If you can't or won't use the Matrix infrastructure, a (possibly fragile) bridge
-to Discord exists
-[here](https://discordapp.com/widget?id=493256121075761173&theme=dark).
+## Features
-
+- Fully configured through a single, easy to understand Python file that lives
+ on a "flash-drive"-esque space on your microcontroller - edit on the go
+ without DFU or other devtooling available!
+- Single-piece or [two-piece split
+ keyboards](https://github.com/KMKfw/kmk_firmware/blob/master/docs/split_keyboards.md)
+ are supported
+- [Chainable
+ keys](https://github.com/KMKfw/kmk_firmware/blob/master/docs/keys.md) such as
+ `KC.LWIN(KC.L)` to lock the screen on a Windows PC
+- [Built-in unicode macros, including
+ emojis](https://github.com/KMKfw/kmk_firmware/blob/master/docs/sequences.md)
+- [Multiple vim-inspired leader key
+ modes](https://github.com/KMKfw/kmk_firmware/blob/master/docs/leader.md)
+- [RGB underglow](https://github.com/KMKfw/kmk_firmware/blob/master/docs/rgb.md)
+ and [LED
+ backlights](https://github.com/KMKfw/kmk_firmware/blob/master/docs/led.md)
+- One key can turn into many more based on [how many times you tap
+ it](https://github.com/KMKfw/kmk_firmware/blob/master/docs/tapdance.md)
-KMK is a firmware for (usually mechanical) keyboards, running on
-[CircuitPython](https://github.com/adafruit/circuitpython). It aims to provide a
-means to write complex keyboard configurations quickly, without having to learn
-much "real" programming, while preserving at least some of the hackability and
-DIY spirit of CircuitPython. Learn more about the rationale of KMK in `Why KMK?`
-below.
+Coming (hopefully) soon: Bluetooth support! Stay tuned.
-This project is currently written and maintained by:
+## Getting Started
-- [Josh Klar (@klardotsh)](https://github.com/klardotsh)
+- Start by grabbing a supported microcontroller. Broadly speaking, KMK supports
+ any device CircuitPython does, but KMK requires a decent bit of RAM, and in
+ general requires a working USB HID stack, which leads us to recommend the
+ following controllers:
+
+ * [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800)\*
+ * [Adafruit Feather M4 Express](https://www.adafruit.com/product/3857)
+ * [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
+ * [MakerDiary nRF52840 MDK](https://store.makerdiary.com/collections/frontpage/products/nrf52840-mdk-iot-development-kit)
+ * [SparkFun Pro nRF52840 Mini](https://www.sparkfun.com/products/15025)
+
+ > \* The ItsyBitsy M4 Express is the only controller we currently support in
+ > non-handwired configurations, using our [ItsyBitsy to Pro Micro converter
+ > PCB](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) designed by
+ > @siddacious and @kdb424. It is our most-recommended MCU until [the ItsyBitsy is
+ > updated with an nRF52840
+ > chip](https://blog.adafruit.com/2019/01/26/comingsoon-itsybitsy-nrf52480-runs-circuitpython-adafruit-circuitpython-adafruit-circuitpython/)
+
+ > Some other controllers, such as the [Feather M0 Express](https://www.adafruit.com/product/3403),
+ > are usable in reduced functionality modes and may require custom hackery.
+ > For example, @kdb424 uses a ItsyBitsy M0 Express as a barebones matrix scanner
+ > in a split keyboard configuration
+ > [here](https://github.com/KMKfw/kmk_firmware/commit/1f84079dc8aadeb9627c4762d9f9fb855292c4a2).
+ > Use such controllers at your own risk.
+
+- Ensure CircuitPython 4.0.0 or newer is installed on your controller. We
+ recommend the latest stable version from
+ [circuitpython.org](https://circuitpython.org/downloads). Flashing
+ instructions vary by device: all Adafruit boards can be flashed [using their
+ instructions](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython),
+ other boards generally have their instructions [in the CircuitPython
+ repository](https://github.com/adafruit/circuitpython) under the
+ `ports/atmel-samd/boards/` and `ports/nrf/boards/` directories. If all else fails, consult your device's official
+ documentation.
+
+- [Download the latest KMK release](https://cdn.kmkfw.io/kmk-latest.zip) and
+ extract the zip to the USB drive exposed by CircuitPython, typically labeled
+ `CIRCUITPY`. Again, [we'll defer to Adafruit's
+ documentation](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries)
+ on adding libraries to a CircuitPython installation.
+
+- Define your keyboard in a file called `main.py` on this `CIRCUITPY` drive and
+ get tinkering! Examples of both handwired and ProMicro-\>ItsyBitsy converted
+ boards exist under the `user_keymaps/` tree, and feel free to submit a pull
+ request of your own definitions! At this point, you'll want to look through
+ `docs/` in the source tree to explore the functionality at your disposal.
+
+> Linux, BSD, and MacOS users can also make use of the `Makefile` provided in
+> this source tree to flash KMK and a keymap using `rsync`. This is advanced
+> functionality outside the scope of this README, but it's documented in the
+> `docs/` tree.
+
+## The KMK Team
+
+KMK is primarily written and maintained by @klardotsh and @kdb424, but
+contributions are welcome from all, whether it's in the form of code,
+documentation, hardware designs, feature ideas, or anything else that comes to
+mind. KMK's contributors and other helpers are listed alphabetically by username
+below (we'll try to keep this up to date!):
+
+- [Dan Halbert (@dhalbert)](https://github.com/dhalbert)
+- [Elvis Pfützenreuter (@elvis-epx)](https://github.com/elvis-epx)
- [Kyle Brown (@kdb424)](https://github.com/kdb424)
-
-With community help from:
-
+- [Josh Klar (@klardotsh)](https://github.com/klardotsh)
+- [Limor Fried (@ladyada)](https://github.com/ladyada)
+- [Ryan Karpinski (@rk463345)](https://github.com/rk463345)
- [@siddacious](https://github.com/siddacious)
- [Scott Shawcroft (@tannewt)](https://github.com/tannewt)
-> Scott is the lead developer of the CircuitPython project itself at Adafruit.
-> KMK, however, is not officially sponsored by Adafruit, and is an independent
-> project.
-
-Lastly, we'd like to make a couple of shoutouts to people not directly
-affiliated with the project in any way, but who have helped or inspired us along
-the way:
-
-- [Jack Humbert (@jackhumbert)](https://jackhumbert.com/), for writing QMK.
- Without QMK, I'd have never been exposed to the wonderful world of
- programmable keyboards. He's also just an awesometastic human in general, if
- you ever catch him on Discord/Reddit/etc. Jack also makes fantastic hardware -
- check out [his store](https://olkb.com)!
-
-- [Dan Halbert (@dhalbert)](https://danhalbert.org/), for his amazing and
- unjudgemental support of two random dudes on Github asking all sorts of
- bizzare (okay... and occasionally dumb) questions on the MicroPython and
- CircuitPython Github projects and the Adafruit Discord. Dan, without your help
- and pointers (even when those pointers are "Remember you're working with a
- microcontroller with a few MHz of processing speed and a few KB of RAM"), this
- project would have never gotten off the ground. Thank you, and an extended
- thanks to Adafruit.
-
-## Why KMK?
-
-A question we get from time to time is, "why bother with KMK when QMK already
-exists?", so here's a short bulleted list of our thoughts on the matter (in no
-particular order):
-
-- Python is awesome
-- Python is super easy to write
-- KMK cut all the "tech debt" of supporting AVR controllers, and frankly even
- most ARM controllers with under 256KB of flash. This let us make some very
- user-friendly (in our biased opinions) design decisions that should make it
- simple for users to create even fairly complex keyboards - want a key on your
- board that sends a shruggie (`¯\_(ツ)_/¯`)? No problem - it's supported out of
- the box. Want a single key that can act as all 26 alphabet characters
- depending on the number of times it's tapped? You're insane, but our simple
- Tap Dance implementation has you covered (without a single line of matrix
- mangling or timer madness)
-- KMK supports a few small features QMK doesn't - most are probably not
- deal-closers, but they exist no less..
-- KMK plans to support some fairly powerful hardware that would enable things
- like connecting halves (or thirds, or whatever) of a split keyboard to each
- other via Bluetooth. This stuff is still in very early R&D.
-
-## So how do I use it?
-
-Since KMK is still in beta currently. Flashing KMK to a
-board is still a process that requires a few lines of shell scripting. Check out
-`docs/flashing.md` for instructions/details, though note that for now, the
-instructions mostly assume Unix (Linux/MacOS/BSD) usage. You may want to check
-out the Windows Subsystem for Linux if you're on Windows.
+> While Adafruit employees and affiliates are included in the above list and
+> their help has been crucial to KMK's success, KMK is not an official Adafruit
+> project, and the Core team is not compensated by Adafruit for its development.
## License, Copyright, and Legal
-Most files in this project are licensed
-[GPLv3](https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)) -
-see `LICENSE.md` at the top of this source tree for exceptions and the full
-license text.
+All software in this repository is licensed under the [GNU Public License,
+verison 3](https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)).
+All documentation and hardware designs are licensed under the [Creative Commons
+Attribution-ShareAlike 4.0](https://creativecommons.org/licenses/by-sa/4.0/)
+license. Contributions to this repository must use these licenses unless
+otherwise agreed to by the Core team.
-When contributing for the first time, you'll need to sign a Contributor
+When you open your first pull request, you'll be asked to sign a Contributor
Licensing Agreement which is based on the Free Software Foundation's CLA. The
-CLA is basically a two-way promise that this code is and remains yours, but will
-be distributed as part of a larger GPLv3 project. If you'd like to get it out of
-the way early, you can find said CLA [here](
-https://cla-assistant.io/kmkfw/kmk_firmware). If you forget, the bots will
-remind you when you open the pull request, no worries!
+CLA is basically a two-way promise that your code is and remains yours, but will
+be distributed as part of a larger GPL project. This CLA can be read and/or
+signed [here](https://cla-assistant.io/kmkfw/kmk_firmware).
diff --git a/docs/flashing.md b/docs/flashing.md
index cdd2918..9069e66 100644
--- a/docs/flashing.md
+++ b/docs/flashing.md
@@ -1,45 +1,35 @@
# Flashing Instructions
-KMK sits on top of an existing CircuitPython install, flash that for your board
-as appropriate (see [Adafruit's
-documentation](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython),
-though it doesn't cover all CircuitPython boards - you may need to glance around
-the CircuitPython source or ask on Discord). We primarily target CircuitPython
-4.0-alpha1 to 4.0-alpha2. You'll only need
-to flash CircuitPython once (unless we update our baseline supported version).
+In general, we recommend using the instructions in `README.md`, however, mostly
+as a development artifact, another method of flashing KMK exists (tested and
+supported only on Linux, though it should also work on MacOS, the BSDs, and
+other Unix-likes. It may also work on Cygwin and the Windows Subsystem for
+Linux).
-After CircuitPython has been flashed, a `CIRCUITPY` drive should show up on your
-computer most likely. If not, check out the troubleshooting section below.
+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
+the file defined as `USER_KEYMAP` as your `main.py`. If any of these files exist
+on your CircuitPython device already, they will be overwritten without a prompt.
-# Windows
-Currently, we do not have an official "flasher" for windows. You can manually install it fairly easily and we recommend
-checking out the support page to join the community if you have any questions. An actual tool is in development.
-Alternatively, you can flash from any linux like tool set (Cygwin, WSL, ect) using the Linux guide below.
-
-# Mac
-Until an interactive installer is created, please follow the linux instructions replacing /mnt with /Volumes
-
-# Linux
-
-While in the directory for kmk, simply run this, changing the mount point and keymap name to whatever is appropriate.
+If you get permissions errors here, **don't run make as root or with sudo**. See
+`Troubleshooting` below.
```sh
-make MOUNTPOINT=/mnt/CIRCUITPY USER_KEYMAP=user_keymaps/nameofyourkeymap.py
+make MOUNTPOINT=/media/CIRCUITPY USER_KEYMAP=user_keymaps/nameofyourkeymap.py
```
# Troubleshooting
-## Windows
-Please check out our support page to get in contact with us and the community and we can gladly help you out.
-
-## Mac
-Please check out our support page to get in contact with us and the community and we can gladly help you out.
-
## Linux/BSD
-Check to see if your drive may have mounted elsewhere with a gui tool. Most will give you the directory in the GUI.
-If it's not mounted, you can read up on how to mount a drive manually [here](https://wiki.archlinux.org/index.php/File_systems#Mount_a_file_system)
-It would look something like this
+Check to see if your drive may have mounted elsewhere with a GUI tool or other
+automounter. Most of these tools will mount your device under `/media`, probably
+as `/media/CIRCUITPY`. If it's not mounted, you can read up on how to mount a
+drive manually
+[here](https://wiki.archlinux.org/index.php/File_systems#Mount_a_file_system).
-`sudo mount -o uid=1000,gid=1000 /dev/sdf1 ~/mnt`
+For example,
-If you still are having issues, check out our support page to see where you can come say hi and the community will gladly help you out.
+`sudo mount -o uid=$(id -u),gid=$(id -g) /dev/disk/by-label/CIRCUITPY ~/mnt`
+
+If you're still having issues, check out our support page to see where you can
+come say hi and the community will gladly help you out.
diff --git a/docs/keymap.md b/docs/keymap.md
index 56245a6..d8651ea 100644
--- a/docs/keymap.md
+++ b/docs/keymap.md
@@ -5,17 +5,17 @@ Keymaps in KMK are simple Python class objects with various attributes assigned
The basics of what you'll need to get started are:
-- Import the `Firmware` object for your keyboard from `kmk.boards` (or, if
- handwiring your keyboard, import `Firmware` from the appropriate MCU for your
+- Import the `KeyboardConfig` object for your keyboard from `kmk.boards` (or, if
+ handwiring your keyboard, import `KeyboardConfig` from the appropriate MCU for your
board from `kmk.mcus`. See `hardware.md` for the list of supported boards and
map this to the correct Python module under either of those paths.
- Add a file to `user_keymaps/your_username` called whatever you'd like
-- Assign a `Firmware` instance to a variable (ex. `keyboard = Firmware()` - note
+- Assign a `KeyboardConfig` instance to a variable (ex. `keyboard = KeyboardConfig()` - note
the parentheses)
-- Make sure this `Firmware` instance is actually run at the end of the file with
+- Make sure this `KeyboardConfig` instance is actually run at the end of the file with
a block such as the following:
```python
@@ -85,14 +85,14 @@ matrix pins (in somewhat of a "spider" setup), utilizing most of the above
features:
```python
-from kmk.boards.klarank import Firmware
+from kmk.boards.klarank import KeyboardConfig
from kmk.consts import UnicodeMode
from kmk.keycodes import KC
from kmk.keycodes import generate_leader_dictionary_seq as glds
from kmk.macros.simple import send_string
from kmk.macros.unicode import compile_unicode_string_sequences as cuss
-keyboard = Firmware()
+keyboard = KeyboardConfig()
keyboard.debug_enabled = True
keyboard.unicode_mode = UnicodeMode.LINUX
diff --git a/docs/tapdance.md b/docs/tapdance.md
index 6215acd..a974734 100644
--- a/docs/tapdance.md
+++ b/docs/tapdance.md
@@ -40,11 +40,11 @@ Here's an example of all this in action:
```python
# user_keymaps/some_silly_example.py
-from kmk.boards.klarank import Firmware
+from kmk.boards.klarank import KeyboardConfig
from kmk.keycodes import KC
from kmk.macros.simple import send_string
-keyboard = Firmware()
+keyboard = KeyboardConfig()
keyboard.tap_time = 750
diff --git a/kmk/boards/converter/fourtypercentclub/gherkin.py b/kmk/boards/converter/fourtypercentclub/gherkin.py
index 83ab43c..3795337 100644
--- a/kmk/boards/converter/fourtypercentclub/gherkin.py
+++ b/kmk/boards/converter/fourtypercentclub/gherkin.py
@@ -1,9 +1,9 @@
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.D9, P.D10, P.D11, P.D12, P.D13, P.SCL)
row_pins = (P.A3, P.A4, P.A5, P.SCK, P.MOSI)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/fourtypercentclub/luddite.py b/kmk/boards/converter/fourtypercentclub/luddite.py
index 99e5ca5..5a41b71 100644
--- a/kmk/boards/converter/fourtypercentclub/luddite.py
+++ b/kmk/boards/converter/fourtypercentclub/luddite.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A0, P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.TX, P.RX, P.SDA, P.SCL, P.D13, P.D12, P.D11, P.D10)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/bdn9.py b/kmk/boards/converter/keebio/bdn9.py
index 1c75906..06d0984 100644
--- a/kmk/boards/converter/keebio/bdn9.py
+++ b/kmk/boards/converter/keebio/bdn9.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.RX, P.D13, P.A0, P.D11, P.A4, P.A5, P.D10, P.D9, P.SCK)
diode_orientation = DiodeOrientation.COLUMNS
rgb_pixel_pin = board.TX
diff --git a/kmk/boards/converter/keebio/fourier.py b/kmk/boards/converter/keebio/fourier.py
index e86a459..f59e042 100644
--- a/kmk/boards/converter/keebio/fourier.py
+++ b/kmk/boards/converter/keebio/fourier.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.A0, P.D11, P.D10, P.D9)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/iris_r1.py b/kmk/boards/converter/keebio/iris_r1.py
index f687a8e..a8c7e11 100644
--- a/kmk/boards/converter/keebio/iris_r1.py
+++ b/kmk/boards/converter/keebio/iris_r1.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.D11, P.D10, P.D9, P.D7, P.D13)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/iris_r2.py b/kmk/boards/converter/keebio/iris_r2.py
index 30bdce2..1646588 100644
--- a/kmk/boards/converter/keebio/iris_r2.py
+++ b/kmk/boards/converter/keebio/iris_r2.py
@@ -1,12 +1,12 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
from kmk.util import intify_coordinate as ic
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
# Pin mappings for converter board found at hardware/README.md
# QMK: MATRIX_COL_PINS { F6, F7, B1, B3, B2, B6 }
# QMK: MATRIX_ROW_PINS { D7, E6, B4, D2, D4 }
diff --git a/kmk/boards/converter/keebio/lapace.py b/kmk/boards/converter/keebio/lapace.py
index 7629fe6..efbb365 100644
--- a/kmk/boards/converter/keebio/lapace.py
+++ b/kmk/boards/converter/keebio/lapace.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.SDA, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.TX, P.A0, P.RX, P.A1, P.D11, P.D9, P.D12, P.D10)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/levinson_r1.py b/kmk/boards/converter/keebio/levinson_r1.py
index 9d622a8..3bffe8d 100644
--- a/kmk/boards/converter/keebio/levinson_r1.py
+++ b/kmk/boards/converter/keebio/levinson_r1.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A2, P.A3, P.A4, P.A5, P.SCK, P.A0)
row_pins = (P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/levinson_r2.py b/kmk/boards/converter/keebio/levinson_r2.py
index c30b9b6..cc85f37 100644
--- a/kmk/boards/converter/keebio/levinson_r2.py
+++ b/kmk/boards/converter/keebio/levinson_r2.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.D13, P.D11, P.D10, P.D9)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/nyquist_r1.py b/kmk/boards/converter/keebio/nyquist_r1.py
index a7b2c51..3a79ada 100644
--- a/kmk/boards/converter/keebio/nyquist_r1.py
+++ b/kmk/boards/converter/keebio/nyquist_r1.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.D13, P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/nyquist_r2.py b/kmk/boards/converter/keebio/nyquist_r2.py
index b0a9699..ea57f25 100644
--- a/kmk/boards/converter/keebio/nyquist_r2.py
+++ b/kmk/boards/converter/keebio/nyquist_r2.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.RX, P.A1, P.A2, P.A3, P.A4, P.A5)
row_pins = (P.D13, P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/quefrency.py b/kmk/boards/converter/keebio/quefrency.py
index a2e7cdc..5b1a76f 100644
--- a/kmk/boards/converter/keebio/quefrency.py
+++ b/kmk/boards/converter/keebio/quefrency.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
# Will need additional work and testing
col_pins = (P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI, P.D12)
row_pins = (P.A0, P.D13, P.D11, P.D10, P.D9, P.D7)
diff --git a/kmk/boards/converter/keebio/rorschach.py b/kmk/boards/converter/keebio/rorschach.py
index 942c19d..bdf3c17 100644
--- a/kmk/boards/converter/keebio/rorschach.py
+++ b/kmk/boards/converter/keebio/rorschach.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.D11, P.D10, P.D9, P.RX, P.D13)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/tragicforce68.py b/kmk/boards/converter/keebio/tragicforce68.py
index 17d6841..812d666 100644
--- a/kmk/boards/converter/keebio/tragicforce68.py
+++ b/kmk/boards/converter/keebio/tragicforce68.py
@@ -1,9 +1,9 @@
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A0, P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.TX, P.RX, P.SDA, P.SCL, P.D9, P.D10, P.D12, P.D11, P.D13)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/viterbi_r1.py b/kmk/boards/converter/keebio/viterbi_r1.py
index 6f5d161..fef2459 100644
--- a/kmk/boards/converter/keebio/viterbi_r1.py
+++ b/kmk/boards/converter/keebio/viterbi_r1.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI)
row_pins = (P.D13, P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/keebio/viterbi_r2.py b/kmk/boards/converter/keebio/viterbi_r2.py
index d273669..c9d156b 100644
--- a/kmk/boards/converter/keebio/viterbi_r2.py
+++ b/kmk/boards/converter/keebio/viterbi_r2.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A0, P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK)
row_pins = (P.D13, P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/lets-split/lets-split_r1.py b/kmk/boards/converter/lets-split/lets-split_r1.py
index c304f44..89d6290 100644
--- a/kmk/boards/converter/lets-split/lets-split_r1.py
+++ b/kmk/boards/converter/lets-split/lets-split_r1.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.A5, P.A4, P.A3, P.A2, P.A1, P.A0)
row_pins = (P.D7, P.D9, P.D10, P.D11)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/converter/lets-split/lets-split_r2.py b/kmk/boards/converter/lets-split/lets-split_r2.py
index 6520bf9..7e9ea8a 100644
--- a/kmk/boards/converter/lets-split/lets-split_r2.py
+++ b/kmk/boards/converter/lets-split/lets-split_r2.py
@@ -1,11 +1,11 @@
import board
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
col_pins = (P.MOSI, P.SCK, P.A5, P.A4, P.A3, P.A2)
row_pins = (P.D11, P.D10, P.D9, P.D7)
diode_orientation = DiodeOrientation.COLUMNS
diff --git a/kmk/boards/klarank.py b/kmk/boards/klarank.py
index 7fde301..a88c1b2 100644
--- a/kmk/boards/klarank.py
+++ b/kmk/boards/klarank.py
@@ -1,9 +1,9 @@
from kmk.consts import DiodeOrientation
-from kmk.mcus.circuitpython_samd51 import Firmware as _Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig as _KeyboardConfig
from kmk.pins import Pin as P
from kmk.util import intify_coordinate as ic
-# Implements what used to be handled by Firmware.swap_indicies for this
+# Implements what used to be handled by KeyboardConfig.swap_indicies for this
# board, by flipping various row3 (bottom physical row) keys so their
# coord_mapping matches what the user pressed (even if the wiring
# underneath is sending different coordinates)
@@ -24,7 +24,7 @@ def r3_swap(col):
return col
-class Firmware(_Firmware):
+class KeyboardConfig(_KeyboardConfig):
# physical, visible cols (SCK, MO, MI, RX, TX, D4)
# physical, visible rows (10, 11, 12, 13) (9, 6, 5, SCL)
col_pins = (P.SCK, P.MOSI, P.MISO, P.RX, P.TX, P.D4)
diff --git a/kmk/consts.py b/kmk/consts.py
index bd3b752..e7b59c8 100644
--- a/kmk/consts.py
+++ b/kmk/consts.py
@@ -1,3 +1,8 @@
+try:
+ from kmk.release_info import KMK_RELEASE
+except Exception:
+ KMK_RELEASE = 'copied-from-git'
+
CIRCUITPYTHON = 'CircuitPython'
MICROPYTHON = 'MicroPython'
diff --git a/kmk/handlers/layers.py b/kmk/handlers/layers.py
index 06a193f..599f4d1 100644
--- a/kmk/handlers/layers.py
+++ b/kmk/handlers/layers.py
@@ -101,10 +101,8 @@ def tt_pressed(key, state, *args, **kwargs):
def tt_released(key, state, *args, **kwargs):
- if (
- state.start_time['tt'] is None or
- ticks_diff(ticks_ms(), state.start_time['tt']) >= state.config.tap_time
- ):
+ tap_timed_out = ticks_diff(ticks_ms(), state.start_time['tt']) >= state.config.tap_time
+ if state.start_time['tt'] is None or tap_timed_out:
# On first press, works like MO. On second press, does nothing unless let up within
# time window, then acts like TG.
state.start_time['tt'] = None
diff --git a/kmk/hid.py b/kmk/hid.py
index a8ca71d..c095628 100644
--- a/kmk/hid.py
+++ b/kmk/hid.py
@@ -183,10 +183,7 @@ else:
self.devices[HIDReportTypes.MOUSE] = device
continue
- if (
- up == HIDUsagePage.SYSCONTROL and
- us == HIDUsage.SYSCONTROL
- ):
+ if up == HIDUsagePage.SYSCONTROL and us == HIDUsage.SYSCONTROL:
self.devices[HIDReportTypes.SYSCONTROL] = device
continue
diff --git a/kmk/internal_state.py b/kmk/internal_state.py
index 82c7107..6a6db5f 100644
--- a/kmk/internal_state.py
+++ b/kmk/internal_state.py
@@ -200,10 +200,10 @@ class InternalState:
if changed_key not in self.tap_side_effects:
self.tap_side_effects[changed_key] = None
else:
- if (
- self.tap_side_effects[changed_key] is not None or
- self.tap_dance_counts[changed_key] == len(changed_key.codes)
- ):
+ has_side_effects = self.tap_side_effects[changed_key] is not None
+ hit_max_defined_taps = self.tap_dance_counts[changed_key] == len(changed_key.codes)
+
+ if has_side_effects or hit_max_defined_taps:
self._end_tap_dance(changed_key)
return self
diff --git a/kmk/firmware.py b/kmk/keyboard_config.py
similarity index 98%
rename from kmk/firmware.py
rename to kmk/keyboard_config.py
index ccc487c..b4fb95b 100644
--- a/kmk/firmware.py
+++ b/kmk/keyboard_config.py
@@ -27,7 +27,7 @@ import kmk.kmktime # isort:skip
import kmk.types # isort:skip
import kmk.util # isort:skip
-from kmk.consts import LeaderMode, UnicodeMode # isort:skip
+from kmk.consts import LeaderMode, UnicodeMode, KMK_RELEASE # isort:skip
from kmk.hid import USB_HID # isort:skip
from kmk.internal_state import InternalState # isort:skip
from kmk.keys import KC # isort:skip
@@ -53,7 +53,7 @@ from kmk.util import intify_coordinate as ic
from kmk import led, rgb # isort:skip
-class Firmware:
+class KeyboardConfig:
debug_enabled = False
keymap = None
@@ -95,7 +95,7 @@ class Firmware:
def __repr__(self):
return (
- 'Firmware('
+ 'KeyboardConfig('
'debug_enabled={} '
'keymap=truncated '
'coord_mapping=truncated '
@@ -152,7 +152,7 @@ class Firmware:
if self.debug_enabled:
if init:
- print('KMKInit()')
+ print('KMKInit(release={})'.format(KMK_RELEASE))
print(self)
print(self._state)
diff --git a/kmk/led.py b/kmk/led.py
index 7aa6f31..d72456f 100644
--- a/kmk/led.py
+++ b/kmk/led.py
@@ -110,8 +110,11 @@ class led:
def effect_breathing(self):
# http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
# https://github.com/qmk/qmk_firmware/blob/9f1d781fcb7129a07e671a46461e501e3f1ae59d/quantum/rgblight.c#L806
- self.brightness = int((exp(sin((self.pos / 255.0) * pi)) - self.breathe_center / e) *
- (self.brightness_limit / (e - 1 / e)))
+ sined = sin((self.pos / 255.0) * pi)
+ multip_1 = exp(sined) - self.breathe_center / e
+ multip_2 = self.brightness_limit / (e - 1 / e)
+
+ self.brightness = int(multip_1 * multip_2)
self.pos = (self.pos + self.animation_speed) % 256
self.set_brightness(self.brightness)
diff --git a/kmk/mcus/circuitpython_samd51.py b/kmk/mcus/circuitpython_samd51.py
deleted file mode 100644
index 7957f26..0000000
--- a/kmk/mcus/circuitpython_samd51.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from kmk.firmware import Firmware as _Firmware
-from kmk.hid import CircuitPythonUSB_HID
-
-
-class Firmware(_Firmware):
- hid_helper = CircuitPythonUSB_HID
diff --git a/kmk/mcus/circuitpython_usbhid.py b/kmk/mcus/circuitpython_usbhid.py
new file mode 100644
index 0000000..16d8530
--- /dev/null
+++ b/kmk/mcus/circuitpython_usbhid.py
@@ -0,0 +1,6 @@
+from kmk.hid import CircuitPythonUSB_HID
+from kmk.keyboard_config import KeyboardConfig as _KeyboardConfig
+
+
+class KeyboardConfig(_KeyboardConfig):
+ hid_helper = CircuitPythonUSB_HID
diff --git a/kmk/rgb.py b/kmk/rgb.py
index d227a6f..1aef3a1 100644
--- a/kmk/rgb.py
+++ b/kmk/rgb.py
@@ -424,8 +424,11 @@ class RGB:
def effect_breathing(self):
# http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
# https://github.com/qmk/qmk_firmware/blob/9f1d781fcb7129a07e671a46461e501e3f1ae59d/quantum/rgblight.c#L806
- self.val = int((exp(sin((self.pos / 255.0) * pi)) - self.breathe_center / e) *
- (self.val_limit / (e - 1 / e)))
+ sined = sin((self.pos / 255.0) * pi)
+ multip_1 = exp(sined) - self.breathe_center / e
+ multip_2 = self.val_limit / (e - 1 / e)
+
+ self.val = int(multip_1 * multip_2)
self.pos = (self.pos + self.animation_speed) % 256
self.set_hsv_fill(self.hue, self.sat, self.val)
diff --git a/linux-udev/99-stm-bootloader.rules b/linux-udev/99-stm-bootloader.rules
deleted file mode 100644
index b87133f..0000000
--- a/linux-udev/99-stm-bootloader.rules
+++ /dev/null
@@ -1 +0,0 @@
-SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", GROUP="uucp", MODE="0660"
diff --git a/setup.cfg b/setup.cfg
index a78aae9..c8b74b0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -7,7 +7,7 @@ per-file-ignores =
user_keymaps/**/*.py: F401,E501,E241,E131
tests/test_data/keymaps/**/*.py: F401,E501
# Forgive me for my RAM hack sins
- kmk/firmware.py: I001,I003,I004,F401
+ kmk/keyboard_config.py: I001,I003,I004,F401
[isort]
known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy,machine,pyb,uos
diff --git a/user_keymaps/default/converter/fourtypercentclub/luddite.py b/user_keymaps/default/converter/fourtypercentclub/luddite.py
index 51d5f69..265af3b 100644
--- a/user_keymaps/default/converter/fourtypercentclub/luddite.py
+++ b/user_keymaps/default/converter/fourtypercentclub/luddite.py
@@ -1,7 +1,7 @@
-from kmk.boards.converter.fourtypercentclub.luddite import Firmware
+from kmk.boards.converter.fourtypercentclub.luddite import KeyboardConfig
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
_______ = KC.TRNS
XXXXXXX = KC.NO
diff --git a/user_keymaps/default/converter/keebio/nyquist_r2.py b/user_keymaps/default/converter/keebio/nyquist_r2.py
index 9a604e5..d5dbc3b 100644
--- a/user_keymaps/default/converter/keebio/nyquist_r2.py
+++ b/user_keymaps/default/converter/keebio/nyquist_r2.py
@@ -1,7 +1,7 @@
-from kmk.boards.converter.keebio.nyquist_r2 import Firmware
+from kmk.boards.converter.keebio.nyquist_r2 import KeyboardConfig
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
_______ = KC.TRNS
XXXXXXX = KC.NO
diff --git a/user_keymaps/kdb424/gherkin.py b/user_keymaps/kdb424/gherkin.py
index 71e9402..615d25d 100644
--- a/user_keymaps/kdb424/gherkin.py
+++ b/user_keymaps/kdb424/gherkin.py
@@ -2,11 +2,11 @@ from kmk.consts import DiodeOrientation, UnicodeMode
from kmk.handlers.sequences import (compile_unicode_string_sequences,
send_string)
from kmk.keys import KC
-from kmk.mcus.circuitpython_samd51 import Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig
from kmk.pins import Pin as P
from kmk.types import AttrDict
-keyboard = Firmware()
+keyboard = KeyboardConfig()
'''
Converter/handwire:
diff --git a/user_keymaps/kdb424/klanck.py b/user_keymaps/kdb424/klanck.py
index 465cd9b..97c3d1a 100644
--- a/user_keymaps/kdb424/klanck.py
+++ b/user_keymaps/kdb424/klanck.py
@@ -2,11 +2,11 @@ from kmk.consts import DiodeOrientation, UnicodeMode
from kmk.handlers.sequences import (compile_unicode_string_sequences,
send_string)
from kmk.keys import KC
-from kmk.mcus.circuitpython_samd51 import Firmware
+from kmk.mcus.circuitpython_usbhid import KeyboardConfig
from kmk.pins import Pin as P
from kmk.types import AttrDict
-keyboard = Firmware()
+keyboard = KeyboardConfig()
keyboard.col_pins = (P.A0, P.A1, P.A2, P.A3, P.A4, P.A5, P.SCK, P.MOSI, P.MISO, P.RX, P.TX, P.D4)
keyboard.row_pins = (P.D10, P.D11, P.D12, P.D13)
diff --git a/user_keymaps/kdb424/levinson_r2.py b/user_keymaps/kdb424/levinson_r2.py
index fae4891..9fd2b70 100644
--- a/user_keymaps/kdb424/levinson_r2.py
+++ b/user_keymaps/kdb424/levinson_r2.py
@@ -1,9 +1,9 @@
-from kmk.boards.converter.keebio.levinson_r2 import Firmware
+from kmk.boards.converter.keebio.levinson_r2 import KeyboardConfig
from kmk.consts import LeaderMode, UnicodeMode
from kmk.handlers.sequences import compile_unicode_string_sequences
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
# ------------------User level config variables ---------------------------------------
keyboard.leader_mode = LeaderMode.TIMEOUT
diff --git a/user_keymaps/kdb424/luddite.py b/user_keymaps/kdb424/luddite.py
index 116c4eb..7dd27ce 100644
--- a/user_keymaps/kdb424/luddite.py
+++ b/user_keymaps/kdb424/luddite.py
@@ -1,7 +1,7 @@
-from kmk.boards.converter.fourtypercentclub.luddite import Firmware
+from kmk.boards.converter.fourtypercentclub.luddite import KeyboardConfig
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
# ---------------------------------- Config --------------------------------------------
diff --git a/user_keymaps/kdb424/nyquist_r2.py b/user_keymaps/kdb424/nyquist_r2.py
index e17f2a6..1ca9a13 100644
--- a/user_keymaps/kdb424/nyquist_r2.py
+++ b/user_keymaps/kdb424/nyquist_r2.py
@@ -1,7 +1,7 @@
-from kmk.boards.converter.keebio.nyquist_r2 import Firmware
+from kmk.boards.converter.keebio.nyquist_r2 import KeyboardConfig
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
# ------------------User level config variables ---------------------------------------
keyboard.tap_time = 150
diff --git a/user_keymaps/klardotsh/iris_r2.py b/user_keymaps/klardotsh/iris_r2.py
index 5402d16..892089c 100644
--- a/user_keymaps/klardotsh/iris_r2.py
+++ b/user_keymaps/klardotsh/iris_r2.py
@@ -1,10 +1,10 @@
-from kmk.boards.converter.keebio.iris_r2 import Firmware
+from kmk.boards.converter.keebio.iris_r2 import KeyboardConfig
from kmk.consts import LeaderMode, UnicodeMode
from kmk.handlers.sequences import compile_unicode_string_sequences as cuss
from kmk.handlers.sequences import send_string
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
keyboard.debug_enabled = False
keyboard.unicode_mode = UnicodeMode.LINUX
diff --git a/user_keymaps/klardotsh/klarank_featherm4.py b/user_keymaps/klardotsh/klarank_featherm4.py
index e8f664a..b6525c7 100644
--- a/user_keymaps/klardotsh/klarank_featherm4.py
+++ b/user_keymaps/klardotsh/klarank_featherm4.py
@@ -1,10 +1,10 @@
-from kmk.boards.klarank import Firmware
+from kmk.boards.klarank import KeyboardConfig
from kmk.consts import LeaderMode, UnicodeMode
from kmk.handlers.sequences import compile_unicode_string_sequences as cuss
from kmk.handlers.sequences import send_string
from kmk.keys import KC, make_key
-keyboard = Firmware()
+keyboard = KeyboardConfig()
keyboard.debug_enabled = True
keyboard.unicode_mode = UnicodeMode.LINUX
diff --git a/user_keymaps/rk463345/levinson_r2.py b/user_keymaps/rk463345/levinson_r2.py
index cc8c05a..ced0733 100755
--- a/user_keymaps/rk463345/levinson_r2.py
+++ b/user_keymaps/rk463345/levinson_r2.py
@@ -1,9 +1,9 @@
-from kmk.boards.converter.keebio.levinson_r2 import Firmware
+from kmk.boards.converter.keebio.levinson_r2 import KeyboardConfig
from kmk.consts import LeaderMode, UnicodeMode
from kmk.handlers.sequences import compile_unicode_string_sequences
from kmk.keys import KC
-keyboard = Firmware()
+keyboard = KeyboardConfig()
# ------------------User level config variables ---------------------------------------
keyboard.leader_mode = LeaderMode.TIMEOUT