1 Commits

Author SHA1 Message Date
xs5871
9c1bd210eb Reduce key dictionary memory footprint
Instead of indexing `Key` objects that have multiple names by each
individual name, index by the set of names. This reduces the size of the
default key dictionary by a factor of between 2 and 3, and as result
also reduces reallocations/defragmentation.
Instead of instantiating all module/extension keys by default, append
them to the `maybe_key`-generator list.
2023-01-31 00:50:54 +00:00
56 changed files with 957 additions and 1054 deletions

View File

@@ -1,23 +0,0 @@
name: build_mpy
on: [push]
jobs:
build:
runs-on: ubuntu-latest
name: Build
steps:
- name: Checkout
uses: actions/checkout@v3
- name: run build script
run: ./docker_mpy_build.sh
- name: look
run: ls -la compiled/
- name: Archive
uses: actions/upload-artifact@v3
with:
name: mpy
path: compiled

View File

@@ -1,20 +1,39 @@
FROM python:3.9-slim-buster
ARG KMKPY_REF
ARG KMKPY_URL
ENV KMKPY_REF ${KMKPY_REF}
ENV KMKPY_URL ${KMKPY_URL}
RUN mkdir -p /app /dist
WORKDIR /app
RUN apt-get update && apt-get install -y curl
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
RUN pip install pipenv
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-8.0.0 --output mpy-cross-8
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-7.0.0 --output mpy-cross-7
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
# inconsistencies with upstream
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
rm -rf /tmp/gcc-arm.tar.bz2
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
# builds for kmkpython anymore, so we can get away with being opinionated
# here.
RUN git init /opt/kmkpython && \
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
git -C /opt/kmkpython checkout FETCH_HEAD && \
git -C /opt/kmkpython submodule update --init --recursive
RUN chmod +x mpy-cross-8
# Build the MPY compiler
RUN make -C /opt/kmkpython/mpy-cross
RUN chmod +x mpy-cross-7
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
COPY ./build_kmkpython_release.sh /app/
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
COPY ./docker_mpy_build.sh /app/build.sh
# COPY ./kmk /app/kmk/
CMD ["bash", "build.sh"]
CMD /app/build_kmkpython_release.sh

View File

@@ -17,6 +17,6 @@ ipython = "*"
isort = "*"
neovim = "*"
s3cmd = "*"
black = "==22.3.0"
black = "==21.6b0"
flake8-quotes = "*"
flake8-black = "*"

426
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "8c1b0ad909dc0ac0fc8013756ca7db8b5420f51c25cc1c2d1612f62fe5e19843"
"sha256": "0a04ec24d4aef6828e4f5eefa0a7d2c312f21f2b2f18c42c7004cdbe0c02bd53"
},
"pipfile-spec": 6,
"requires": {},
@@ -23,12 +23,12 @@
"index": "pypi",
"version": "==1.1.0"
},
"asttokens": {
"appdirs": {
"hashes": [
"sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3",
"sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"
"sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
"sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
],
"version": "==2.2.1"
"version": "==1.4.4"
},
"backcall": {
"hashes": [
@@ -39,32 +39,11 @@
},
"black": {
"hashes": [
"sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b",
"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"
"sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04",
"sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"
],
"index": "pypi",
"version": "==22.3.0"
"version": "==21.6b0"
},
"click": {
"hashes": [
@@ -79,152 +58,144 @@
"sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330",
"sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"
],
"markers": "python_version < '3.11' and python_version >= '3.7'",
"markers": "python_version >= '3.5'",
"version": "==5.1.1"
},
"executing": {
"hashes": [
"sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc",
"sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"
],
"version": "==1.2.0"
},
"flake8": {
"hashes": [
"sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7",
"sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"
"sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b",
"sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"
],
"index": "pypi",
"version": "==6.0.0"
"version": "==3.9.2"
},
"flake8-black": {
"hashes": [
"sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34",
"sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"
"sha256:941514149cb8b489cb17a4bb1cf18d84375db3b34381bb018de83509437931a0",
"sha256:f26651bc10db786c03f4093414f7c9ea982ed8a244cec323c984feeffdf4c118"
],
"index": "pypi",
"version": "==0.3.6"
"version": "==0.2.1"
},
"flake8-commas": {
"hashes": [
"sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263",
"sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"
"sha256:d3005899466f51380387df7151fb59afec666a0f4f4a2c6a8995b975de0f44b7",
"sha256:ee2141a3495ef9789a3894ed8802d03eff1eaaf98ce6d8653a7c573ef101935e"
],
"index": "pypi",
"version": "==2.1.0"
"version": "==2.0.0"
},
"flake8-comprehensions": {
"hashes": [
"sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab",
"sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"
"sha256:b07aef3277623db32310aa241a1cec67212b53c1d18e767d7e26d4d83aa05bf7",
"sha256:f24be9032587127f7a5bc6d066bf755b6e66834f694383adb8a673e229c1f559"
],
"index": "pypi",
"version": "==3.10.1"
"version": "==3.5.0"
},
"flake8-isort": {
"hashes": [
"sha256:537f453a660d7e903f602ecfa36136b140de279df58d02eb1b6a0c84e83c528c",
"sha256:aa0cac02a62c7739e370ce6b9c31743edac904bae4b157274511fc8a19c75bbc"
"sha256:2b91300f4f1926b396c2c90185844eb1a3d5ec39ea6138832d119da0a208f4d9",
"sha256:729cd6ef9ba3659512dee337687c05d79c78e1215fdf921ed67e5fe46cce2f3c"
],
"index": "pypi",
"version": "==6.0.0"
"version": "==4.0.0"
},
"flake8-quotes": {
"hashes": [
"sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"
"sha256:3f1116e985ef437c130431ac92f9b3155f8f652fda7405ac22ffdfd7a9d1055e"
],
"index": "pypi",
"version": "==3.3.2"
"version": "==3.2.0"
},
"greenlet": {
"hashes": [
"sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a",
"sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a",
"sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43",
"sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33",
"sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8",
"sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088",
"sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca",
"sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343",
"sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645",
"sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db",
"sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df",
"sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3",
"sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86",
"sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2",
"sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a",
"sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf",
"sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7",
"sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394",
"sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40",
"sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3",
"sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6",
"sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74",
"sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0",
"sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3",
"sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91",
"sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5",
"sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9",
"sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8",
"sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b",
"sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6",
"sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb",
"sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73",
"sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b",
"sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df",
"sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9",
"sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f",
"sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0",
"sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857",
"sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a",
"sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249",
"sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30",
"sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292",
"sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b",
"sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d",
"sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b",
"sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c",
"sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca",
"sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7",
"sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75",
"sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae",
"sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b",
"sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470",
"sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564",
"sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9",
"sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099",
"sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0",
"sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5",
"sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19",
"sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1",
"sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9",
"sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9",
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581",
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26",
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd",
"sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2",
"sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a",
"sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82",
"sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a",
"sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce",
"sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f",
"sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524",
"sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48",
"sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77",
"sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928",
"sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e",
"sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67",
"sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9",
"sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68",
"sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd",
"sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515",
"sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5",
"sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39",
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94",
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92",
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e",
"sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726",
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd",
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5",
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764",
"sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955",
"sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608",
"sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148",
"sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51",
"sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9",
"sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d",
"sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c",
"sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72",
"sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1",
"sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2",
"sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23",
"sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb",
"sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6",
"sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19",
"sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45",
"sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000",
"sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da",
"sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617",
"sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963",
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7",
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d",
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d",
"sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0",
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243",
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce",
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6",
"sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a",
"sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1",
"sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f",
"sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==2.0.2"
"version": "==2.0.1"
},
"ipdb": {
"hashes": [
"sha256:c23b6736f01fd4586cc2ecbebdf79a5eb454796853e1cd8f2ed3b7b91d4a3e93",
"sha256:f74c2f741c18b909eaf89f19fde973f745ac721744aa1465888ce45813b63a9c"
"sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"
],
"index": "pypi",
"version": "==0.13.11"
"version": "==0.13.9"
},
"ipython": {
"hashes": [
"sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e",
"sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"
"sha256:55df3e0bd0f94e715abd968bedd89d4e8a7bce4bf498fb123fed4f5398fea874",
"sha256:b5548ec5329a4bcf054a5deed5099b0f9622eb9ea51aaa7104d215fece201d8c"
],
"index": "pypi",
"version": "==8.10.0"
"version": "==7.31.1"
},
"isort": {
"hashes": [
"sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504",
"sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6",
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"
],
"index": "pypi",
"version": "==5.12.0"
"version": "==5.8.0"
},
"jedi": {
"hashes": [
@@ -244,11 +215,10 @@
},
"mccabe": {
"hashes": [
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
],
"markers": "python_version >= '3.6'",
"version": "==0.7.0"
"version": "==0.6.1"
},
"msgpack": {
"hashes": [
@@ -309,11 +279,10 @@
},
"mypy-extensions": {
"hashes": [
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
],
"markers": "python_version >= '3.5'",
"version": "==1.0.0"
"version": "==0.4.3"
},
"neovim": {
"hashes": [
@@ -332,11 +301,11 @@
},
"pathspec": {
"hashes": [
"sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229",
"sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"
"sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6",
"sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"
],
"markers": "python_version >= '3.7'",
"version": "==0.11.0"
"version": "==0.10.3"
},
"pexpect": {
"hashes": [
@@ -353,14 +322,6 @@
],
"version": "==0.7.5"
},
"platformdirs": {
"hashes": [
"sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9",
"sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"
],
"markers": "python_version >= '3.7'",
"version": "==3.0.0"
},
"prompt-toolkit": {
"hashes": [
"sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63",
@@ -376,36 +337,29 @@
],
"version": "==0.7.0"
},
"pure-eval": {
"hashes": [
"sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350",
"sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"
],
"version": "==0.2.2"
},
"pycodestyle": {
"hashes": [
"sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
"sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
"sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068",
"sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"
],
"markers": "python_version >= '3.6'",
"version": "==2.10.0"
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.7.0"
},
"pyflakes": {
"hashes": [
"sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf",
"sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"
"sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3",
"sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.1"
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.3.1"
},
"pygments": {
"hashes": [
"sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297",
"sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"
"sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1",
"sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"
],
"markers": "python_version >= '3.6'",
"version": "==2.14.0"
"version": "==2.13.0"
},
"pynvim": {
"hashes": [
@@ -430,27 +384,129 @@
},
"python-dotenv": {
"hashes": [
"sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
"sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
"sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5",
"sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"
],
"markers": "python_version >= '3.7'",
"version": "==0.21.1"
"version": "==0.21.0"
},
"python-magic": {
"hashes": [
"sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b",
"sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"
"sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626",
"sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf"
],
"index": "pypi",
"version": "==0.4.27"
"version": "==0.4.24"
},
"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": {
"hashes": [
"sha256:15330776e7ff993d8ae0ac213bf896f210719e9b91445f5f7626a8fa7e74e30b",
"sha256:2204306742c33c24fbca02b78e059bacfc1bfc04af09c7e9866f267a11a9ddb2"
"sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa",
"sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03"
],
"index": "pypi",
"version": "==2.3.0"
"version": "==2.1.0"
},
"setuptools": {
"hashes": [
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
],
"index": "pypi",
"version": "==65.5.1"
},
"six": {
"hashes": [
@@ -460,35 +516,35 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"stack-data": {
"testfixtures": {
"hashes": [
"sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815",
"sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"
"sha256:02dae883f567f5b70fd3ad3c9eefb95912e78ac90be6c7444b5e2f46bf572c84",
"sha256:7de200e24f50a4a5d6da7019fb1197aaf5abd475efb2ec2422fdcf2f2eb98c1d"
],
"version": "==0.6.2"
"version": "==6.18.5"
},
"tomli": {
"toml": {
"hashes": [
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version < '3.11'",
"version": "==2.0.1"
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"traitlets": {
"hashes": [
"sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8",
"sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"
"sha256:6cc57d6dc28c85d5365961726ffd19b538739347749e13ebe34e03323a0e8f84",
"sha256:c864831efa0ba6576d09b44884b34e41defc18c0d7e720b4a2d6698c842cab3e"
],
"markers": "python_version >= '3.7'",
"version": "==5.9.0"
"version": "==5.8.0"
},
"wcwidth": {
"hashes": [
"sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e",
"sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
],
"version": "==0.2.6"
"version": "==0.2.5"
}
}
}

View File

@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
# Rotary encoder that also acts as a key
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
knob.modules.append(encoder_handler)

View File

@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
# Rotary encoders that also acts as keys
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = (
(board.D1, board.D2, board.D0),
(board.D9, board.D10, board.D3),

View File

@@ -78,7 +78,6 @@ keyboard.keymap = [
# Rotary encoder that also acts as a key
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
keyboard.modules.append(encoder_handler)

View File

@@ -1,12 +0,0 @@
# 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

View File

@@ -1,97 +0,0 @@
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()

3
boot.py Normal file → Executable file
View File

@@ -0,0 +1,3 @@
import supervisor
supervisor.set_next_stack_limit(4096 + 4096)

View File

View File

@@ -1,7 +0,0 @@
version: '3.3'
services:
mpy_kmk:
build: .
volumes:
- ./kmk:/app/kmk
- ./.compiled:/app/compiled

View File

@@ -1,14 +0,0 @@
#!/bin/sh
echo "building mpy"
echo $(ls compiled)
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/8/$(dirname {}) &&\
./mpy-cross-8 -O2 {} -o compiled/8/$(dirname {})/$(basename -s .py {}).mpy' \;
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/7/$(dirname {}) &&\
./mpy-cross-7 -O2 {} -o compiled/7/$(dirname {})/$(basename -s .py {}).mpy' \;
echo $(ls compiled)
echo "done building"

View File

@@ -76,10 +76,8 @@ You can also get ideas from the various [user examples](https://github.com/KMKfw
In case you need it, debugging help can be found [here](debugging.md)
For asynchronous support and chatter about KMK, [join our Zulip
community](https://kmkfw.zulipchat.com)!
If you ask for help in chat or open a bug report, if possible
If you need support with KMK or just want to say hi, find us in
[#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is
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
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.

View File

@@ -6,7 +6,8 @@ to make contributing as easy as possible for everyone while maintaining a consis
## Contributing Code
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,
feel free to [join our Zulip community](https://kmkfw.zulipchat.com).
feel free to join the chat, [#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh).
This channel is bridged to Discord [here](https://discord.gg/QBHUUpeGUd) for convenience.
### Code Style

View File

@@ -1,7 +1,6 @@
# Stringy Keymaps
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.
Enables referring to keys by `'NAME'` rather than `KC.NAME`.
For example:
@@ -14,9 +13,6 @@ from kmk.extensions.stringy_keymaps import StringyKeymaps
# Indexed
# keyboard.keymap = [[ KC['A'], KC['B'], KC['RESET'] ]]
# String names mixed with normal keycodes
# keyboard.keymap = [[ 'A' , KC.B, KC.RESET ]]
# String names
keyboard.keymap = [[ 'A' , 'B', 'RESET' ]]
@@ -31,5 +27,3 @@ keyboard.extensions.append(stringyKeymaps)
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.
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.

View File

@@ -9,7 +9,9 @@ Linux).
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`. It will also copy our
`boot.py`. If any of these files exist on your CircuitPython device already, they
`boot.py`, which allocates a larger stack size (simply - more of the device's
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.
If you get permissions errors here, **don't run make as root or with sudo**. See

View File

@@ -1,9 +1,9 @@
# Support
For asynchronous support and chatter about KMK, [join our Zulip
community](https://kmkfw.zulipchat.com)!
If you need support with KMK or just want to say hi, find us in [#kmkfw:klar.sh
on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is 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
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.

View File

@@ -96,7 +96,8 @@ RGB や分裂型などの機能を楽しめたい場合は、ビルトイン[モ
デバッグについてのヘルプが必要な場合は[こちら](debugging.md)。
KMK についてサポートが必要な場合や、コミュニケーションをとりたい場合は[こちら](https://kmkfw.zulipchat.com)。
KMK についてサポートが必要な場合や、コミュニケーションをとりたい場合は[こちら](https://matrix.to/#/#kmkfw:klar.sh)。
このチャネルは[Discord](https://discordapp.com/widget?id=493256121075761173&theme=dark) からも見ることができます。
チャットで助けを求める場合やバグ レポートを開く場合は、可能であれば KMK
のコピーが最新であることを確認してください。

View File

@@ -123,6 +123,8 @@ 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).
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
canal [kmkfw no Zulip](https://kmkfw.zulipchat.com).
Se você precisa de ajuda ou pretende abrir um bug report, se
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal
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
possível se possível, verifique se sua cópia do KMK está atualizada.

View File

@@ -1,7 +1,10 @@
# Suporte
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
canal [no Zulip](https://kmkfw.zulipchat.com).
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal
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
possível se possível, verifique se sua cópia do KMK está atualizada.

View File

@@ -1,35 +1,42 @@
'''Adds international keys'''
from kmk.extensions import Extension
from kmk.keys import make_key
from kmk.keys import KC, make_key
class International(Extension):
'''Adds international keys'''
def __init__(self):
# International
make_key(code=50, names=('NONUS_HASH', 'NUHS'))
make_key(code=100, names=('NONUS_BSLASH', 'NUBS'))
make_key(code=101, names=('APP', 'APPLICATION', 'SEL', 'WINMENU'))
KC._generators.append(self.maybe_make_media_key)
make_key(code=135, names=('INT1', 'RO'))
make_key(code=136, names=('INT2', 'KANA'))
make_key(code=137, names=('INT3', 'JYEN'))
make_key(code=138, names=('INT4', 'HENK'))
make_key(code=139, names=('INT5', 'MHEN'))
make_key(code=140, names=('INT6',))
make_key(code=141, names=('INT7',))
make_key(code=142, names=('INT8',))
make_key(code=143, names=('INT9',))
make_key(code=144, names=('LANG1', 'HAEN'))
make_key(code=145, names=('LANG2', 'HAEJ'))
make_key(code=146, names=('LANG3',))
make_key(code=147, names=('LANG4',))
make_key(code=148, names=('LANG5',))
make_key(code=149, names=('LANG6',))
make_key(code=150, names=('LANG7',))
make_key(code=151, names=('LANG8',))
make_key(code=152, names=('LANG9',))
@staticmethod
def maybe_make_media_key(candidate):
codes = (
(50, ('NONUS_HASH', 'NUHS')),
(100, ('NONUS_BSLASH', 'NUBS')),
(101, ('APP', 'APPLICATION', 'SEL', 'WINMENU')),
(135, ('INT1', 'RO')),
(136, ('INT2', 'KANA')),
(137, ('INT3', 'JYEN')),
(138, ('INT4', 'HENK')),
(139, ('INT5', 'MHEN')),
(140, ('INT6',)),
(141, ('INT7',)),
(142, ('INT8',)),
(143, ('INT9',)),
(144, ('LANG1', 'HAEN')),
(145, ('LANG2', 'HAEJ')),
(146, ('LANG3',)),
(147, ('LANG4',)),
(148, ('LANG5',)),
(149, ('LANG6',)),
(150, ('LANG7',)),
(151, ('LANG8',)),
(152, ('LANG9',)),
)
for code, names in codes:
if candidate in names:
return make_key(code=code, names=names)
def on_runtime_enable(self, sandbox):
return

View File

@@ -2,7 +2,8 @@ import pwmio
from math import e, exp, pi, sin
from kmk.extensions import Extension, InvalidExtensionEnvironment
from kmk.keys import make_argumented_key, make_key
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key, make_key
from kmk.utils import clamp
@@ -61,35 +62,51 @@ class LED(Extension):
if user_animation is not None:
self.user_animation = user_animation
make_argumented_key(
names=('LED_TOG',),
KC._generators.append(self.maybe_make_led_key())
def maybe_make_led_key(self):
argumented_keys = (
(
('LED_TOG',),
self._key_led_tog,
),
(
('LED_INC',),
self._key_led_inc,
),
(
('LED_DEC',),
self._key_led_dec,
),
(
('LED_SET',),
self._key_led_set,
),
)
keys = (
(('LED_ANI',), self._key_led_ani),
(('LED_AND',), self._key_led_and),
(('LED_MODE_PLAIN', 'LED_M_P'), self._key_led_mode_static),
(('LED_MODE_BREATHE', 'LED_M_B'), self._key_led_mode_breathe),
)
def closure(candidate):
for names, on_press in argumented_keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=self._led_key_validator,
on_press=self._key_led_tog,
on_press=on_press,
on_release=handler_passthrough,
)
make_argumented_key(
names=('LED_INC',),
validator=self._led_key_validator,
on_press=self._key_led_inc,
)
make_argumented_key(
names=('LED_DEC',),
validator=self._led_key_validator,
on_press=self._key_led_dec,
)
make_argumented_key(
names=('LED_SET',),
validator=self._led_set_key_validator,
on_press=self._key_led_set,
)
make_key(names=('LED_ANI',), on_press=self._key_led_ani)
make_key(names=('LED_AND',), on_press=self._key_led_and)
make_key(
names=('LED_MODE_PLAIN', 'LED_M_P'), on_press=self._key_led_mode_static
)
make_key(
names=('LED_MODE_BREATHE', 'LED_M_B'), on_press=self._key_led_mode_breathe
for names, on_press in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=handler_passthrough
)
return closure
def __repr__(self):
return f'LED({self._to_dict()})'

View File

@@ -1,9 +1,13 @@
from kmk.extensions import Extension
from kmk.keys import make_consumer_key
from kmk.keys import KC, make_consumer_key
class MediaKeys(Extension):
def __init__(self):
KC._generators.append(self.maybe_make_media_key)
@staticmethod
def maybe_make_media_key(candidate):
# Consumer ("media") keys. Most known keys aren't supported here. A much
# longer list used to exist in this file, but the codes were almost certainly
# incorrect, conflicting with each other, or otherwise 'weird'. We'll add them
@@ -14,20 +18,23 @@ class MediaKeys(Extension):
# support PC media keys, so I don't know how much value we would get out of
# adding the old Apple-specific consumer codes, but again, PRs welcome if the
# lack of them impacts you.
make_consumer_key(code=226, names=('AUDIO_MUTE', 'MUTE')) # 0xE2
make_consumer_key(code=233, names=('AUDIO_VOL_UP', 'VOLU')) # 0xE9
make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD')) # 0xEA
make_consumer_key(code=111, names=('BRIGHTNESS_UP', 'BRIU')) # 0x6F
make_consumer_key(code=112, names=('BRIGHTNESS_DOWN', 'BRID')) # 0x70
make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT')) # 0xB5
make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV')) # 0xB6
make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP')) # 0xB7
make_consumer_key(
code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY')
) # 0xCD (this may not be right)
make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8
make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3
make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4
codes = (
(226, ('AUDIO_MUTE', 'MUTE')), # 0xE2
(233, ('AUDIO_VOL_UP', 'VOLU')), # 0xE9
(234, ('AUDIO_VOL_DOWN', 'VOLD')), # 0xEA
(111, ('BRIGHTNESS_UP', 'BRIU')), # 0x6F
(112, ('BRIGHTNESS_DOWN', 'BRID')), # 0x70
(181, ('MEDIA_NEXT_TRACK', 'MNXT')), # 0xB5
(182, ('MEDIA_PREV_TRACK', 'MPRV')), # 0xB6
(183, ('MEDIA_STOP', 'MSTP')), # 0xB7
(205, ('MEDIA_PLAY_PAUSE', 'MPLY')), # 0xCD (this may not be right)
(184, ('MEDIA_EJECT', 'EJCT')), # 0xB8
(179, ('MEDIA_FAST_FORWARD', 'MFFD')), # 0xB3
(180, ('MEDIA_REWIND', 'MRWD')), # 0xB4
)
for code, names in codes:
if candidate in names:
return make_consumer_key(code=code, names=names)
def on_runtime_enable(self, sandbox):
return

View File

@@ -4,7 +4,7 @@ from storage import getmount
from kmk.extensions import Extension
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key
from kmk.keys import KC, make_key
class Color:
@@ -69,16 +69,35 @@ class Rgb_matrix(Extension):
else:
self.ledDisplay = ledDisplay
make_key(
names=('RGB_TOG',), on_press=self._rgb_tog, on_release=handler_passthrough
KC._generators.append(self.maybe_make_peg_rgb_key())
def maybe_make_peg_rgb_key(self):
keys = (
(
('RGB_TOG',),
self._rgb_tog,
),
(
('RGB_BRI',),
self._rgb_bri,
),
(
('RGB_BRD',),
self._rgb_brd,
),
)
make_key(
names=('RGB_BRI',), on_press=self._rgb_bri, on_release=handler_passthrough
)
make_key(
names=('RGB_BRD',), on_press=self._rgb_brd, on_release=handler_passthrough
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def _rgb_tog(self, *args, **kwargs):
if self.enable:
self.off()

View File

@@ -3,7 +3,7 @@ from math import e, exp, pi, sin
from kmk.extensions import Extension
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key
from kmk.keys import KC, make_key
from kmk.kmktime import PeriodicTimer
from kmk.utils import Debug, clamp
@@ -157,69 +157,37 @@ class RGB(Extension):
self._substep = 0
make_key(
names=('RGB_TOG',), on_press=self._rgb_tog, on_release=handler_passthrough
KC._generators.append(self.maybe_make_rgb_key())
def maybe_make_rgb_key(self):
keys = (
(('RGB_TOG',), self._rgb_tog),
(('RGB_HUI',), self._rgb_hui),
(('RGB_HUD',), self._rgb_hud),
(('RGB_SAI',), self._rgb_sai),
(('RGB_SAD',), self._rgb_sad),
(('RGB_VAI',), self._rgb_vai),
(('RGB_VAD',), self._rgb_vad),
(('RGB_ANI',), self._rgb_ani),
(('RGB_AND',), self._rgb_and),
(('RGB_MODE_PLAIN', 'RGB_M_P'), self._rgb_mode_static),
(('RGB_MODE_BREATHE', 'RGB_M_B'), self._rgb_mode_breathe),
(('RGB_MODE_RAINBOW', 'RGB_M_R'), self._rgb_mode_rainbow),
(('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), self._rgb_mode_breathe_rainbow),
(('RGB_MODE_SWIRL', 'RGB_M_S'), self._rgb_mode_swirl),
(('RGB_MODE_KNIGHT', 'RGB_M_K'), self._rgb_mode_knight),
(('RGB_RESET', 'RGB_RST'), self._rgb_reset),
)
make_key(
names=('RGB_HUI',), on_press=self._rgb_hui, on_release=handler_passthrough
)
make_key(
names=('RGB_HUD',), on_press=self._rgb_hud, on_release=handler_passthrough
)
make_key(
names=('RGB_SAI',), on_press=self._rgb_sai, on_release=handler_passthrough
)
make_key(
names=('RGB_SAD',), on_press=self._rgb_sad, on_release=handler_passthrough
)
make_key(
names=('RGB_VAI',), on_press=self._rgb_vai, on_release=handler_passthrough
)
make_key(
names=('RGB_VAD',), on_press=self._rgb_vad, on_release=handler_passthrough
)
make_key(
names=('RGB_ANI',), on_press=self._rgb_ani, on_release=handler_passthrough
)
make_key(
names=('RGB_AND',), on_press=self._rgb_and, on_release=handler_passthrough
)
make_key(
names=('RGB_MODE_PLAIN', 'RGB_M_P'),
on_press=self._rgb_mode_static,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_BREATHE', 'RGB_M_B'),
on_press=self._rgb_mode_breathe,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_RAINBOW', 'RGB_M_R'),
on_press=self._rgb_mode_rainbow,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'),
on_press=self._rgb_mode_breathe_rainbow,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_SWIRL', 'RGB_M_S'),
on_press=self._rgb_mode_swirl,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_KNIGHT', 'RGB_M_K'),
on_press=self._rgb_mode_knight,
on_release=handler_passthrough,
)
make_key(
names=('RGB_RESET', 'RGB_RST'),
on_press=self._rgb_reset,
on_release=handler_passthrough,
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=handler_passthrough
)
return closure
def on_runtime_enable(self, sandbox):
return

View File

@@ -4,7 +4,8 @@ import pwmio
import time
from kmk.extensions import Extension, InvalidExtensionEnvironment
from kmk.keys import make_key
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_key
class statusLED(Extension):
@@ -32,8 +33,24 @@ class statusLED(Extension):
self.brightness_step = brightness_step
self.brightness_limit = brightness_limit
make_key(names=('SLED_INC',), on_press=self._key_led_inc)
make_key(names=('SLED_DEC',), on_press=self._key_led_dec)
KC._generators.append(self.maybe_make_status_led_key())
def maybe_make_status_led_key(self):
keys = (
(('SLED_INC',), self._key_led_inc),
(('SLED_DEC',), self._key_led_dec),
)
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def _layer_indicator(self, layer_active, *args, **kwargs):
'''

View File

@@ -35,7 +35,7 @@ def simple_key_sequence(seq):
meta=KeySequenceMeta(seq),
on_press=sequence_press_handler,
on_release=passthrough,
)
)[0]
def send_string(message):
@@ -124,7 +124,7 @@ def unicode_codepoint_sequence(codepoints):
simple_key_sequence(_winc_unicode_sequence(kc_macros, keyboard)), True
)
return make_key(on_press=_unicode_sequence)
return make_key(on_press=_unicode_sequence)[0]
def _ralt_unicode_sequence(kc_macros, keyboard):

View File

@@ -127,13 +127,3 @@ def ble_refresh(key, keyboard, *args, **kwargs):
keyboard._hid_helper.stop_advertising()
keyboard._hid_helper.start_advertising()
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

View File

@@ -4,8 +4,7 @@ from micropython import const
from storage import getmount
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey, MouseKey
from kmk.utils import clamp
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey
try:
from adafruit_ble import BLERadio
@@ -69,14 +68,6 @@ class AbstractHID:
self.report_mods = memoryview(self._evt)[1:2]
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()
def __repr__(self):
@@ -85,27 +76,47 @@ class AbstractHID:
def post_init(self):
pass
def create_report(self, keys_pressed, axes):
def create_report(self, keys_pressed):
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:
if key.code >= FIRST_KMK_INTERNAL_KEY:
continue
if isinstance(key, ModifierKey):
self.add_modifier(key)
elif isinstance(key, ConsumerKey):
self.add_cc(key)
elif isinstance(key, MouseKey):
self.add_pd(key)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
for axis in axes:
self.move_axis(axis)
return self
def hid_send(self, evt):
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
@@ -120,24 +131,12 @@ class AbstractHID:
self._prev_evt[:] = 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
def clear_all(self):
for idx, _ in enumerate(self.report_keys):
self.report_keys[idx] = 0x00
self.remove_cc()
self.remove_pd()
self.clear_axis()
return self
def clear_non_modifiers(self):
@@ -176,6 +175,9 @@ class AbstractHID:
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):
if where_to_place[idx] == 0x00:
where_to_place[idx] = key.code
@@ -191,44 +193,15 @@ class AbstractHID:
def remove_key(self, key):
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):
if where_to_place[idx] == key.code:
where_to_place[idx] = 0x00
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):
REPORT_BYTES = 9

View File

@@ -20,7 +20,6 @@ class KeyType:
SIMPLE = const(0)
MODIFIER = const(1)
CONSUMER = const(2)
MOUSE = const(3)
FIRST_KMK_INTERNAL_KEY = const(1000)
@@ -34,32 +33,9 @@ ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
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(
code: Optional[int],
names: Tuple[str, ...],
code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA
*args,
**kwargs,
) -> Callable[[str], Key]:
@@ -364,7 +340,6 @@ def maybe_make_unicode_key(candidate: str) -> Optional[Key]:
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
keys = (
((('BLE_REFRESH',), handlers.ble_refresh)),
((('BLE_DISCONNECT',), handlers.ble_disconnect)),
((('BOOTLOADER',), handlers.bootloader)),
((('DEBUG', 'DBG'), handlers.debug_pressed)),
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
@@ -425,51 +400,34 @@ KEY_GENERATORS = (
class KeyAttrDict:
# 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 = [{}]
__cache = {}
_generators = list(KEY_GENERATORS)
def __iter__(self):
for partition in self.__cache:
for name in partition.__iter__():
yield name
return self.__cache.__iter__()
def __setitem__(self, name: str, key: Key):
# Overwrite existing reference.
for partition in self.__cache:
if name in partition:
partition[name] = key
return key
def __setitem__(self, key: str, value: Key):
self.__cache.__setitem__(key, value)
# Insert new reference.
if len(self.__cache[-1]) >= self.__partition_size:
self.__cache.append({})
self.__cache[-1][name] = key
return key
def __getattr__(self, key: Key):
return self.__getitem__(key)
def __getattr__(self, name: str):
return self.__getitem__(name)
def get(self, name: str, default: Optional[Key] = None):
def get(self, key: Key, default: Optional[Key] = None):
try:
return self.__getitem__(name)
return self.__getitem__(key)
except Exception:
return default
def clear(self):
self.__cache.clear()
self.__cache.append({})
self._generators = list(KEY_GENERATORS)
def __getitem__(self, name: str):
for partition in self.__cache:
if name in partition:
return partition[name]
for names, key in self.__cache.items():
if name in names:
return key
for func in KEY_GENERATORS:
for func in self._generators:
maybe_key = func(name)
if maybe_key:
break
@@ -477,10 +435,15 @@ class KeyAttrDict:
if not maybe_key:
raise ValueError(f'Invalid key: {name}')
if debug.enabled:
debug(f'{name}: {maybe_key}')
key, names = maybe_key
return maybe_key
if names:
self.__cache[names] = key
if debug.enabled:
debug(f'{name}: {key}')
return key
# Global state, will be filled in throughout this file, and
@@ -713,13 +676,9 @@ class ConsumerKey(Key):
pass
class MouseKey(Key):
pass
def make_key(
code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA
names: Optional[Tuple[str, ...]] = tuple(), # NOQA
type: KeyType = KeyType.SIMPLE,
**kwargs,
) -> Key:
@@ -747,8 +706,6 @@ def make_key(
constructor = ModifierKey
elif type == KeyType.CONSUMER:
constructor = ConsumerKey
elif type == KeyType.MOUSE:
constructor = MouseKey
else:
raise ValueError('Unrecognized key type')
@@ -763,10 +720,7 @@ def make_key(
key = constructor(code=code, **kwargs)
for name in names:
KC[name] = key
return key
return key, names
def make_mod_key(code: int, names: Tuple[str, ...], *args, **kwargs) -> Key:
@@ -781,10 +735,6 @@ def make_consumer_key(*args, **kwargs) -> Key:
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
# is almost certainly the best plan here
def make_argumented_key(
@@ -816,7 +766,4 @@ def make_argumented_key(
'should have been raised.'
)
for name in names:
KC[name] = _argumented_key
return _argumented_key
return _argumented_key, names

View File

@@ -49,7 +49,6 @@ class KMKKeyboard:
#####
# Internal State
keys_pressed = set()
axes = set()
_coordkeys_pressed = {}
hid_type = HIDModes.USB
secondary_hid_type = None
@@ -89,7 +88,6 @@ class KMKKeyboard:
f' unicode_mode={self.unicode_mode}, ',
f'_hid_helper={self._hid_helper},\n',
f' keys_pressed={self.keys_pressed},\n',
f' axes={self.axes},\n',
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
f' hid_pending={self.hid_pending}, ',
f'active_layers={self.active_layers}, ',
@@ -104,24 +102,15 @@ class KMKKeyboard:
debug(f'keys_pressed={self.keys_pressed}')
def _send_hid(self) -> None:
if not self._hid_send_enabled:
return
if self.axes and debug.enabled:
debug(f'axes={self.axes}')
self._hid_helper.create_report(self.keys_pressed, self.axes)
if self._hid_send_enabled:
hid_report = self._hid_helper.create_report(self.keys_pressed)
try:
self._hid_helper.send()
hid_report.send()
except KeyError as e:
if debug.enabled:
debug(f'HidNotFound(HIDReportType={e})')
self.hid_pending = False
for axis in self.axes:
axis.move(self, 0)
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
if kevent is not None:
self._on_matrix_changed(kevent)

View File

@@ -4,9 +4,9 @@ import microcontroller
import time
from kmk.keys import AX
from kmk.modules import Module
from kmk.modules.adns9800_firmware import firmware
from kmk.modules.mouse_keys import PointingDevice
class REG:
@@ -70,6 +70,7 @@ class ADNS9800(Module):
DIR_READ = 0x7F
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
self.pointing_device = PointingDevice()
self.cs = digitalio.DigitalInOut(cs)
self.cs.direction = digitalio.Direction.OUTPUT
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
@@ -202,14 +203,27 @@ class ADNS9800(Module):
if self.invert_y:
delta_y *= -1
if delta_x:
AX.X.move(delta_x)
if delta_x < 0:
self.pointing_device.report_x[0] = (delta_x & 0xFF) | 0x80
else:
self.pointing_device.report_x[0] = delta_x & 0xFF
if delta_y:
AX.Y.move(delta_y)
if delta_y < 0:
self.pointing_device.report_y[0] = (delta_y & 0xFF) | 0x80
else:
self.pointing_device.report_y[0] = delta_y & 0xFF
if keyboard.debug_enabled:
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):
return

View File

@@ -1,4 +1,5 @@
from kmk.keys import FIRST_KMK_INTERNAL_KEY, KC, ModifierKey, make_key
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import FIRST_KMK_INTERNAL_KEY, KC, ModifierKey, maybe_make_key
from kmk.modules import Module
@@ -16,12 +17,16 @@ class CapsWord(Module):
self._timeout_key = False
self._cw_active = False
self.timeout = timeout
make_key(
KC._generators.append(self.maybe_make_capsword_key())
def maybe_make_capsword_key(self):
return maybe_make_key(
names=(
'CAPSWORD',
'CW',
),
on_press=self.cw_pressed,
on_release=handler_passthrough,
)
def during_bootup(self, keyboard):

View File

@@ -1,3 +1,4 @@
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, ModifierKey, make_key
from kmk.modules import Module
@@ -12,16 +13,26 @@ class CgSwap(Module):
KC.LGUI: KC.LCTL,
KC.RGUI: KC.RCTL,
}
make_key(
names=('CG_SWAP',),
KC._generators.append(self.maybe_make_cgswap_key())
def maybe_make_cgswap_key(self):
keys = (
(('CG_SWAP',),),
(('CG_NORM',),),
(('CG_TOGG',),),
)
make_key(
names=('CG_NORM',),
)
make_key(
names=('CG_TOGG',),
def closure(candidate):
for names in keys:
if candidate in names:
return make_key(
names=names,
on_press=handler_passthrough,
on_release=handler_passthrough,
)
return closure
def during_bootup(self, keyboard):
return

View File

@@ -5,7 +5,7 @@ except ImportError:
from micropython import const
import kmk.handlers.stock as handlers
from kmk.keys import Key, make_key
from kmk.keys import KC, Key, maybe_make_key
from kmk.kmk_keyboard import KMKKeyboard
from kmk.modules import Module
@@ -102,12 +102,13 @@ class Combos(Module):
def __init__(self, combos=[]):
self.combos = combos
self._key_buffer = []
make_key(
KC._generators.append(
maybe_make_key(
names=('LEADER', 'LDR'),
on_press=handlers.passthrough,
on_release=handlers.passthrough,
)
)
def during_bootup(self, keyboard):
self.reset(keyboard)

View File

@@ -3,6 +3,7 @@ from supervisor import ticks_ms
from collections import namedtuple
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key
from kmk.kmktime import check_deadline, ticks_diff
from kmk.modules import Module
@@ -45,41 +46,33 @@ class DynamicSequences(Module):
self.index = 0
self.start_time = 0
self.current_repetition = 0
self.last_config_frame = set()
self.timeout = timeout
self.key_interval = key_interval
self.use_recorded_speed = use_recorded_speed
# Create keycodes
make_argumented_key(
validator=DSMeta, names=('RECORD_SEQUENCE',), on_press=self._record_sequence
KC._generators.append(self.maybe_make_sequence_key())
def maybe_make_sequence_key(self):
keys = (
(('RECORD_SEQUENCE',), DSMeta, self._record_sequence),
(('PLAY_SEQUENCE',), DSMeta, self._play_sequence),
(('SET_SEQUENCE', 'STOP_SEQUENCE'), DSMeta, self._stop_sequence),
(('SET_SEQUENCE_REPETITIONS',), DSMeta, self._set_sequence_repetitions),
(('SET_SEQUENCE_INTERVAL',), DSMeta, self._set_sequence_interval),
)
make_argumented_key(
validator=DSMeta, names=('PLAY_SEQUENCE',), on_press=self._play_sequence
def closure(candidate):
for names, validator, on_press in keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=on_press,
on_release=handler_passthrough,
)
make_argumented_key(
validator=DSMeta,
names=(
'SET_SEQUENCE',
'STOP_SEQUENCE',
),
on_press=self._stop_sequence,
)
make_argumented_key(
validator=DSMeta,
names=('SET_SEQUENCE_REPETITIONS',),
on_press=self._set_sequence_repetitions,
)
make_argumented_key(
validator=DSMeta,
names=('SET_SEQUENCE_INTERVAL',),
on_press=self._set_sequence_interval,
)
return closure
def _record_sequence(self, key, keyboard, *args, **kwargs):
self._stop_sequence(key, keyboard)

View File

@@ -4,8 +4,8 @@ Extension handles usage of AS5013 by AMS
from supervisor import ticks_ms
from kmk.keys import AX
from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice
I2C_ADDRESS = 0x40
I2X_ALT_ADDRESS = 0x41
@@ -44,6 +44,7 @@ class Easypoint(Module):
self._i2c_bus = i2c
# HID parameters
self.pointing_device = PointingDevice()
self.polling_interval = 20
self.last_tick = ticks_ms()
@@ -81,8 +82,12 @@ class Easypoint(Module):
return
else:
# Set the X/Y from easypoint
AX.X.move(keyboard, x)
AX.Y.move(keyboard, y)
self.pointing_device.report_x[0] = x
self.pointing_device.report_y[0] = y
self.pointing_device.hid_pending = x != 0 or y != 0
return
def after_matrix_scan(self, keyboard):
return
@@ -91,6 +96,9 @@ class Easypoint(Module):
return
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
def on_powersave_enable(self, keyboard):
@@ -99,13 +107,20 @@ class Easypoint(Module):
def on_powersave_disable(self, keyboard):
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):
'''Read data from AS5013'''
x, y = self._i2c_rdwr([X], length=2)
return x, y
def getSignedNumber(self, number, bitLength=8):
mask = (2**bitLength) - 1
mask = (2 ** bitLength) - 1
if number & (1 << (bitLength - 1)):
return number | ~mask
else:

View File

@@ -1,6 +1,6 @@
from micropython import const
from kmk.keys import KC, make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module
from kmk.utils import Debug
@@ -55,12 +55,14 @@ class HoldTap(Module):
self.key_buffer = []
self.key_states = {}
if not KC.get('HT'):
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
validator=HoldTapKeyMeta,
names=('HT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
)
)
def during_bootup(self, keyboard):
return

View File

@@ -1,4 +1,5 @@
'''One layer isn't enough. Adds keys to get to more of them'''
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key
from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta
from kmk.utils import Debug
@@ -39,46 +40,31 @@ class Layers(HoldTap):
def __init__(self):
# Layers
super().__init__()
make_argumented_key(
validator=layer_key_validator,
names=('MO',),
on_press=self._mo_pressed,
on_release=self._mo_released,
KC._generators.append(self.maybe_make_layer_key())
def maybe_make_layer_key(self):
keys = (
(('MO',), layer_key_validator, self._mo_pressed, self._mo_released),
(('DF',), layer_key_validator, self._df_pressed, handler_passthrough),
(('LM',), layer_key_validator, self._lm_pressed, self._lm_released),
(('TG',), layer_key_validator, self._tg_pressed, handler_passthrough),
(('TO',), layer_key_validator, self._to_pressed, handler_passthrough),
(('LT',), layer_key_validator_lt, self.ht_pressed, self.ht_released),
(('TT',), layer_key_validator_tt, self.ht_pressed, self.ht_released),
)
make_argumented_key(
validator=layer_key_validator,
names=('DF',),
on_press=self._df_pressed,
)
make_argumented_key(
validator=layer_key_validator,
names=('LM',),
on_press=self._lm_pressed,
on_release=self._lm_released,
)
make_argumented_key(
validator=layer_key_validator,
names=('TG',),
on_press=self._tg_pressed,
)
make_argumented_key(
validator=layer_key_validator,
names=('TO',),
on_press=self._to_pressed,
)
make_argumented_key(
validator=layer_key_validator_lt,
names=('LT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
)
make_argumented_key(
validator=layer_key_validator_tt,
names=('TT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
def closure(candidate):
for names, validator, on_press, on_release in keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=on_press,
on_release=on_release,
)
return closure
def _df_pressed(self, key, keyboard, *args, **kwargs):
'''
Switches the default layer
@@ -114,15 +100,17 @@ class Layers(HoldTap):
'''
As MO(layer) but with mod active
'''
keyboard.hid_pending = True
# Sets the timer start and acts like MO otherwise
keyboard.add_key(key.meta.kc)
keyboard.keys_pressed.add(key.meta.kc)
self._mo_pressed(key, keyboard, *args, **kwargs)
def _lm_released(self, key, keyboard, *args, **kwargs):
'''
As MO(layer) but with mod active
'''
keyboard.remove_key(key.meta.kc)
keyboard.hid_pending = True
keyboard.keys_pressed.discard(key.meta.kc)
self._mo_released(key, keyboard, *args, **kwargs)
def _tg_pressed(self, key, keyboard, *args, **kwargs):

View File

@@ -8,7 +8,8 @@ from adafruit_midi.program_change import ProgramChange
from adafruit_midi.start import Start
from adafruit_midi.stop import Stop
from kmk.keys import make_argumented_key
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key
from kmk.modules import Module
@@ -21,42 +22,6 @@ class midiNoteValidator:
class MidiKeys(Module):
def __init__(self):
make_argumented_key(
names=('MIDI_CC',),
validator=ControlChange,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_NOTE',),
validator=midiNoteValidator,
on_press=self.note_on,
on_release=self.note_off,
)
make_argumented_key(
names=('MIDI_PB',),
validator=PitchBend,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_PC',),
validator=ProgramChange,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_START',),
validator=Start,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_STOP',),
validator=Stop,
on_press=self.on_press,
)
try:
self.midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
@@ -65,6 +30,37 @@ class MidiKeys(Module):
# if debug_enabled:
print('No midi device found.')
KC._generators.append(self.maybe_make_midi_key())
def maybe_make_midi_key(self):
keys = (
(('MIDI_CC',), ControlChange),
(('MIDI_PB',), PitchBend),
(('MIDI_PC',), ProgramChange),
(('MIDI_START',), Start),
(('MIDI_STOP',), Stop),
)
note = ('MIDI_NOTE',)
def closure(candidate):
if candidate in note:
return make_argumented_key(
names=('MIDI_NOTE',),
validator=midiNoteValidator,
on_press=self.note_on,
on_release=self.note_off,
)
for names, validator in keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=self.on_press,
on_release=handler_passthrough,
)
return closure
def during_bootup(self, keyboard):
return None

View File

@@ -1,13 +1,15 @@
from kmk.keys import make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta
class ModTap(HoldTap):
def __init__(self):
super().__init__()
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
validator=HoldTapKeyMeta,
names=('MT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
)
)

View File

@@ -1,6 +1,7 @@
from supervisor import ticks_ms
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
from kmk.keys import AX, make_key, make_mouse_key
from kmk.kmktime import PeriodicTimer
from kmk.keys import KC, make_key
from kmk.modules import Module
@@ -23,100 +24,73 @@ class PointingDevice:
class MouseKeys(Module):
def __init__(self):
self.pointing_device = PointingDevice()
self._nav_key_activated = 0
self._up_activated = False
self._down_activated = False
self._left_activated = False
self._right_activated = False
self._mw_up_activated = False
self._mw_down_activated = False
self.max_speed = 10
self.acc_interval = 10 # Delta ms to apply acceleration
self.ac_interval = 100 # Delta ms to apply acceleration
self._next_interval = 0 # Time for next tick interval
self.move_step = 1
KC._generators.append(self.maybe_make_mouse_key())
make_mouse_key(
names=('MB_LMB',),
code=1,
def maybe_make_mouse_key(self):
keys = (
(('MB_LMB',), self._mb_lmb_press, self._mb_lmb_release),
(('MB_MMB',), self._mb_mmb_press, self._mb_mmb_release),
(('MB_RMB',), self._mb_rmb_press, self._mb_rmb_release),
(('MW_UP',), self._mw_up_press, self._mw_up_release),
(('MW_DOWN', 'MW_DN'), self._mw_down_press, self._mw_down_release),
(('MS_UP',), self._ms_up_press, self._ms_up_release),
(('MS_DOWN', 'MS_DN'), self._ms_down_press, self._ms_down_release),
(('MS_LEFT', 'MS_LT'), self._ms_left_press, self._ms_left_release),
(('MS_RIGHT', 'MS_RT'), self._ms_right_press, self._ms_right_release),
)
make_mouse_key(
names=('MB_MMB',),
code=4,
)
make_mouse_key(
names=('MB_RMB',),
code=2,
)
make_key(
names=('MW_UP',),
on_press=self._mw_up_press,
on_release=self._mw_up_release,
)
make_key(
names=(
'MW_DOWN',
'MW_DN',
),
on_press=self._mw_down_press,
on_release=self._mw_down_release,
)
make_key(
names=('MS_UP',),
on_press=self._ms_up_press,
on_release=self._ms_up_release,
)
make_key(
names=(
'MS_DOWN',
'MS_DN',
),
on_press=self._ms_down_press,
on_release=self._ms_down_release,
)
make_key(
names=(
'MS_LEFT',
'MS_LT',
),
on_press=self._ms_left_press,
on_release=self._ms_left_release,
)
make_key(
names=(
'MS_RIGHT',
'MS_RT',
),
on_press=self._ms_right_press,
on_release=self._ms_right_release,
def closure(candidate):
for names, on_press, on_release in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=on_release
)
return closure
def during_bootup(self, keyboard):
self._timer = PeriodicTimer(self.acc_interval)
return
def matrix_detected_press(self, keyboard):
return keyboard.matrix_update is None
def before_matrix_scan(self, keyboard):
return
def after_matrix_scan(self, keyboard):
if not self._timer.tick():
return
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:
self.move_step = self.move_step + 1
if self._right_activated:
AX.X.move(keyboard, self.move_step)
self.pointing_device.report_x[0] = self.move_step
if self._left_activated:
AX.X.move(keyboard, -self.move_step)
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
if self._up_activated:
AX.Y.move(keyboard, -self.move_step)
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
if self._down_activated:
AX.Y.move(keyboard, self.move_step)
if self._mw_up_activated:
AX.W.move(keyboard, 1)
if self._mw_down_activated:
AX.W.move(keyboard, -1)
self.pointing_device.report_y[0] = self.move_step
self.pointing_device.hid_pending = True
return
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
def after_hid_send(self, keyboard):
@@ -128,21 +102,50 @@ class MouseKeys(Module):
def on_powersave_disable(self, keyboard):
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):
self._mw_up_activated = True
self.pointing_device.report_w[0] = self.move_step
self.pointing_device.hid_pending = True
def _mw_up_release(self, key, keyboard, *args, **kwargs):
self._mw_up_activated = False
self.pointing_device.report_w[0] = 0
self.pointing_device.hid_pending = True
def _mw_down_press(self, key, keyboard, *args, **kwargs):
self._mw_down_activated = True
self.pointing_device.report_w[0] = 0xFF
self.pointing_device.hid_pending = True
def _mw_down_release(self, key, keyboard, *args, **kwargs):
self._mw_down_activated = False
self.pointing_device.report_w[0] = 0
self.pointing_device.hid_pending = True
# Mouse movement
def _reset_next_interval(self):
if self._nav_key_activated == 1:
self._next_interval = ticks_ms() + self.ac_interval
self.move_step = 1
def _check_last(self):
@@ -153,38 +156,56 @@ class MouseKeys(Module):
self._nav_key_activated += 1
self._reset_next_interval()
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):
self._up_activated = False
self._nav_key_activated -= 1
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):
self._nav_key_activated += 1
self._reset_next_interval()
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):
self._down_activated = False
self._nav_key_activated -= 1
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):
self._nav_key_activated += 1
self._reset_next_interval()
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):
self._nav_key_activated -= 1
self._left_activated = False
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):
self._nav_key_activated += 1
self._reset_next_interval()
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):
self._nav_key_activated -= 1
self._right_activated = False
self._check_last()
self.pointing_device.report_x[0] = 0
self.pointing_device.hid_pending = False

View File

@@ -1,4 +1,4 @@
from kmk.keys import make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
@@ -11,12 +11,14 @@ class OneShot(HoldTap):
def __init__(self):
super().__init__()
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
validator=oneshot_validator,
names=('OS', 'ONESHOT'),
on_press=self.osk_pressed,
on_release=self.osk_released,
)
)
def process_key(self, keyboard, current_key, is_pressed, int_coord):
'''Release os key after interrupting keyup.'''

View File

@@ -7,9 +7,10 @@ from micropython import const
import math
import struct
from kmk.keys import AX, KC, make_argumented_key, make_key
from kmk.keys import KC, maybe_make_argumented_key, maybe_make_key
from kmk.kmktime import PeriodicTimer
from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice
I2C_ADDRESS = 0x0A
I2C_ADDRESS_ALTERNATIVE = 0x0B
@@ -77,16 +78,29 @@ class TrackballHandler:
class PointingHandler(TrackballHandler):
def handle(self, keyboard, trackball, x, y, switch, state):
if x:
AX.X.move(keyboard, x)
if y:
AX.Y.move(keyboard, y)
if x > 0:
trackball.pointing_device.report_x[0] = x
elif x < 0:
trackball.pointing_device.report_x[0] = 0xFF & x
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:
trackball.pointing_device.hid_pending = True
if switch == 1: # Button pressed
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
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
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
trackball.pointing_device.button_status[
0
] &= ~trackball.pointing_device.MB_LMB
trackball.pointing_device.hid_pending = True
trackball.previous_state = state
@@ -100,13 +114,17 @@ class ScrollHandler(TrackballHandler):
y = -y
if y != 0:
AX.W.move(keyboard, y)
pointing_device = trackball.pointing_device
pointing_device.report_w[0] = 0xFF & y
pointing_device.hid_pending = True
if switch == 1: # Button pressed
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
pointing_device.button_status[0] |= pointing_device.MB_LMB
pointing_device.hid_pending = True
if not state and trackball.previous_state is True: # Button released
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
pointing_device.button_status[0] &= ~pointing_device.MB_LMB
pointing_device.hid_pending = True
trackball.previous_state = state
@@ -167,6 +185,7 @@ class Trackball(Module):
self._i2c_address = address
self._i2c_bus = i2c
self.pointing_device = PointingDevice()
self.mode = mode
self.previous_state = False # click state
self.handlers = handlers
@@ -179,16 +198,19 @@ class Trackball(Module):
f'Invalid chip ID: 0x{chip_id:04X}, expected 0x{CHIP_ID:04X}'
)
make_key(
KC._generators.append(
maybe_make_key(
names=('TB_MODE', 'TB_NEXT_HANDLER', 'TB_N'),
on_press=self._tb_handler_next_press,
)
make_argumented_key(
)
KC._generators.append(
maybe_make_argumented_key(
validator=layer_key_validator,
names=('TB_HANDLER', 'TB_H'),
on_press=self._tb_handler_press,
)
)
def during_bootup(self, keyboard):
self._timer = PeriodicTimer(self.polling_interval)
@@ -215,6 +237,9 @@ class Trackball(Module):
return
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
def on_powersave_enable(self, keyboard):
@@ -258,6 +283,13 @@ class Trackball(Module):
next_index = 0
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):
'''Read up, down, left, right and switch data from trackball.'''
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)

View File

@@ -5,7 +5,7 @@ from supervisor import ticks_ms
from time import sleep
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key
from kmk.keys import KC, make_key
from kmk.kmktime import check_deadline
from kmk.modules import Module
@@ -20,16 +20,26 @@ class Power(Module):
self._i2c = 0
self._loopcounter = 0
make_key(
names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough
KC._generators.append(self.maybe_make_power_key())
def maybe_make_power_key(self):
keys = (
(('PS_TOG',), self._ps_tog),
(('PS_ON',), self._ps_enable),
(('PS_OFF',), self._ps_disable),
)
make_key(
names=('PS_ON',), on_press=self._ps_enable, on_release=handler_passthrough
)
make_key(
names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def __repr__(self):
return f'Power({self._to_dict()})'

View File

@@ -1,6 +1,6 @@
from random import randint
from kmk.keys import make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module
@@ -28,12 +28,14 @@ class RapidFire(Module):
_waiting_keys = []
def __init__(self):
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
validator=RapidFireMeta,
names=('RF',),
on_press=self._rf_pressed,
on_release=self._rf_released,
)
)
def _get_repeat(self, key):
if key.meta.enable_interval_randomization:

View File

@@ -1,4 +1,4 @@
from kmk.keys import make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module
@@ -12,12 +12,14 @@ class StickyMod(Module):
def __init__(self):
self._active = False
self._active_key = None
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
names=('SM',),
validator=StickyModMeta,
on_press=self.sm_pressed,
on_release=self.sm_released,
)
)
def during_bootup(self, keyboard):
return

View File

@@ -1,4 +1,4 @@
from kmk.keys import KC, make_argumented_key
from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
@@ -30,12 +30,14 @@ class TapDanceKeyMeta:
class TapDance(HoldTap):
def __init__(self):
super().__init__()
make_argumented_key(
KC._generators.append(
maybe_make_argumented_key(
validator=TapDanceKeyMeta,
names=('TD',),
on_press=self.td_pressed,
on_release=self.td_released,
)
)
self.td_counts = {}

View File

@@ -1,39 +0,0 @@
FROM python:3.9-slim-buster
ARG KMKPY_REF
ARG KMKPY_URL
ENV KMKPY_REF ${KMKPY_REF}
ENV KMKPY_URL ${KMKPY_URL}
RUN mkdir -p /app /dist
WORKDIR /app
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
RUN pip install pipenv
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
# inconsistencies with upstream
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
rm -rf /tmp/gcc-arm.tar.bz2
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
# builds for kmkpython anymore, so we can get away with being opinionated
# here.
RUN git init /opt/kmkpython && \
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
git -C /opt/kmkpython checkout FETCH_HEAD && \
git -C /opt/kmkpython submodule update --init --recursive
# Build the MPY compiler
RUN make -C /opt/kmkpython/mpy-cross
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
COPY ./build_kmkpython_release.sh /app/
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
CMD /app/build_kmkpython_release.sh

Binary file not shown.

Binary file not shown.

View File

@@ -9,6 +9,9 @@ from tests.keyboard_test import KeyboardTest
class TestHoldTap(unittest.TestCase):
def setUp(self):
KC.clear()
def test_holdtap(self):
keyboard = KeyboardTest(
[Layers(), ModTap(), OneShot()],

View File

@@ -1,6 +1,6 @@
import unittest
from kmk.keys import KC, Key, ModifierKey, make_key
from kmk.keys import KC, Key, ModifierKey, make_key, maybe_make_key
from tests.keyboard_test import KeyboardTest
@@ -131,20 +131,14 @@ class TestKeys_dot(unittest.TestCase):
KC.invalid_key
def test_custom_key(self):
created = make_key(
KC._generators.append(
maybe_make_key(
KC.N2.code,
names=(
'EURO',
'',
),
names=('EURO', ''),
has_modifiers={KC.LSFT.code, KC.ROPT.code},
)
assert created is KC.get('EURO')
assert created is KC.get('')
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC.get('ThIs_Is_A_StRaNgE_kEy')
)
assert KC.get('') is KC.get('EURO')
class TestKeys_index(unittest.TestCase):
@@ -176,20 +170,14 @@ class TestKeys_index(unittest.TestCase):
KC['not_a_valid_key']
def test_custom_key(self):
created = make_key(
KC['N2'].code,
names=(
'EURO',
'',
),
has_modifiers={KC['LSFT'].code, KC['ROPT'].code},
KC._generators.append(
maybe_make_key(
KC.N2.code,
names=('EURO', ''),
has_modifiers={KC.LSFT.code, KC.ROPT.code},
)
assert created is KC['EURO']
assert created is KC['']
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC['ThIs_Is_A_StRaNgE_kEy']
)
assert KC.get('') is KC.get('EURO')
class TestKeys_get(unittest.TestCase):
@@ -224,20 +212,14 @@ class TestKeys_get(unittest.TestCase):
assert KC.get('not_a_valid_key') is None
def test_custom_key(self):
created = make_key(
KC.get('N2').code,
names=(
'EURO',
'',
),
has_modifiers={KC.get('LSFT').code, KC.get('ROPT').code},
KC._generators.append(
maybe_make_key(
KC.N2.code,
names=('EURO', ''),
has_modifiers={KC.LSFT.code, KC.ROPT.code},
)
assert created is KC.get('EURO')
assert created is KC.get('')
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC.get('ThIs_Is_A_StRaNgE_kEy')
)
assert KC.get('') is KC.get('EURO')
def test_underscore(self):
assert KC.get('_')
@@ -251,8 +233,8 @@ class TestKeys_instances(unittest.TestCase):
KC.clear()
def test_make_key_new_instance(self):
key1 = make_key(code=1)
key2 = make_key(code=1)
key1, _ = make_key(code=1)
key2, _ = make_key(code=1)
assert key1 is not key2
assert key1.code == key2.code

View File

@@ -7,6 +7,7 @@ from tests.keyboard_test import KeyboardTest
class TestLayers(unittest.TestCase):
def setUp(self):
KC.clear()
self.kb = KeyboardTest(
[Layers()],
[

View File

@@ -9,6 +9,7 @@ from tests.keyboard_test import KeyboardTest
class TestTapDance(unittest.TestCase):
def setUp(self):
KC.clear()
self.keyboard = KeyboardTest(
[Layers(), HoldTap(), TapDance()],
[