39 Commits

Author SHA1 Message Date
cole
370eb151e2 removed unused file 2023-02-19 19:54:25 -08:00
cole
d0b93bd275 cleaning up 2023-02-19 19:30:50 -08:00
cole
f1f5ac01bd more striping 2023-02-19 19:26:51 -08:00
cole
8101f98860 why use docker inside 2023-02-19 19:17:23 -08:00
cole
3b4c00b1bb working on work flow 2023-02-19 19:06:31 -08:00
cole
4518983b36 workflow file 2023-02-19 19:00:25 -08:00
cole
d5106dd5e2 editing build script 2023-02-19 18:44:10 -08:00
cole
730a18437c editing build script 2023-02-19 18:39:49 -08:00
cole
1ae2de4315 working on work flow 2023-02-19 18:33:27 -08:00
cole
8bcaa7a235 working on work flow 2023-02-19 18:28:45 -08:00
cole
b2ae0d364a docker compose version bump 2023-02-19 18:21:20 -08:00
cole
51528cbb41 docker compose version bump 2023-02-19 18:17:31 -08:00
cole
db4030f49b working on work flow 2023-02-19 18:12:24 -08:00
cole
fb87de1d85 working on work flow 2023-02-19 18:11:07 -08:00
cole
f65f436273 made new docker file to build mpy files 2023-02-19 18:09:02 -08:00
xs5871
a90d569690 Fix CC HID report generation 2023-02-18 08:20:52 +00:00
xs5871
449aab7dcb Add BLE_DISCONNECT key 2023-02-17 03:03:40 +00:00
Stefan Misch
dc9b5f4512 fix encoder resolution for MacroPad10 2023-02-16 09:07:48 +00:00
Stefan Misch
cbaddef9a6 fix encoder resolution for Knobs3 2023-02-16 09:07:48 +00:00
Stefan Misch
804b5ec575 fix: encoder resolution for Knob 1 2023-02-16 09:07:48 +00:00
xs5871
a28df47199 Refactor affected modules to use global pointing device 2023-02-14 20:42:08 +00:00
xs5871
9e5d2c24e1 Refactor for nicer pointing device axes handling 2023-02-14 20:42:08 +00:00
xs5871
ca800331de Implement axis movement method 2023-02-14 20:42:08 +00:00
xs5871
1ca27dab58 refactor mouse_keys to use PeriodicTimer 2023-02-14 20:42:08 +00:00
xs5871
fc8d5edd52 refactor mouse_keys module to use global pd 2023-02-14 20:42:08 +00:00
xs5871
e84bbd0d75 add mouse buttons to pointing device 2023-02-14 20:42:08 +00:00
xs5871
69d47343e8 implement global pointing device axis handling 2023-02-14 20:42:08 +00:00
xs5871
470f16c97f factor out consumer control from keyboard hid 2023-02-14 20:42:08 +00:00
xs5871
27f101d139 remove hid awareness from layer module 2023-02-14 20:42:08 +00:00
xs5871
2852420ea8 Bump black version 2023-02-12 22:32:39 +00:00
moritz-john
5a38af6632 Update docs/en/extension_stringy_keymaps.md
Co-authored-by: xs5871 <60395129+xs5871@users.noreply.github.com>
2023-02-12 19:45:18 +00:00
Moritz John
fa7d72b175 Added more examples to the Stringy Keymaps docs
Rearranged text

Removed blank lines

Fixed "string name" to "string"

Enclosed string in single qutoes
2023-02-12 19:45:18 +00:00
xs5871
d7e9cfbc5b Replace all mentions of the matrix channel with links to zulip 2023-02-12 17:25:24 +00:00
xs5871
408f2f487e Remove for-else-block from keys.py for readability 2023-02-11 21:27:41 +00:00
xs5871
5af52addf8 Fixes KeyAttrDict iterator 2023-02-11 21:27:41 +00:00
xs5871
705d3eb032 Remove supervisor stack limit from boot.py 2023-02-11 20:05:45 +00:00
dependabot[bot]
638d64af72 Bump ipython from 7.31.1 to 8.10.0
Bumps [ipython](https://github.com/ipython/ipython) from 7.31.1 to 8.10.0.
- [Release notes](https://github.com/ipython/ipython/releases)
- [Commits](https://github.com/ipython/ipython/compare/7.31.1...8.10.0)

---
updated-dependencies:
- dependency-name: ipython
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-11 09:13:27 +00:00
xs5871
e7427ff53b Split KeyAttrDict.__cache into memory friendly partitions. 2023-02-11 09:03:44 +00:00
Leon Anavi
62d6bf16df anavi/macro-pad-12: Add ANAVI Macro Pad 12
Add support for ANAVI Macro Pad 12: an open source programmable
small hot-swappable mechanical keyboard with 12 keys, mini OLED
I2C display and Seeed XIAO RP2040. This is an open source hardware
designed with KiCad.

Signed-off-by: Leon Anavi <leon@anavi.org>
2023-02-07 22:20:59 +00:00
33 changed files with 645 additions and 543 deletions

23
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
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,39 +1,20 @@
FROM python:3.9-slim-buster FROM python:3.9-slim-buster
ARG KMKPY_REF RUN mkdir -p /app /dist
ARG KMKPY_URL WORKDIR /app
ENV KMKPY_REF ${KMKPY_REF} RUN apt-get update && apt-get install -y curl
ENV KMKPY_URL ${KMKPY_URL}
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 mkdir -p /app /dist 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
WORKDIR /app
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2 RUN chmod +x mpy-cross-8
RUN pip install pipenv
RUN chmod +x 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 && \ COPY ./docker_mpy_build.sh /app/build.sh
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \ # COPY ./kmk /app/kmk/
rm -rf /tmp/gcc-arm.tar.bz2
CMD ["bash", "build.sh"]
# 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

View File

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

426
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "0a04ec24d4aef6828e4f5eefa0a7d2c312f21f2b2f18c42c7004cdbe0c02bd53" "sha256": "8c1b0ad909dc0ac0fc8013756ca7db8b5420f51c25cc1c2d1612f62fe5e19843"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@@ -23,12 +23,12 @@
"index": "pypi", "index": "pypi",
"version": "==1.1.0" "version": "==1.1.0"
}, },
"appdirs": { "asttokens": {
"hashes": [ "hashes": [
"sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3",
"sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"
], ],
"version": "==1.4.4" "version": "==2.2.1"
}, },
"backcall": { "backcall": {
"hashes": [ "hashes": [
@@ -39,11 +39,32 @@
}, },
"black": { "black": {
"hashes": [ "hashes": [
"sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04", "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b",
"sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7" "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176",
"sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09",
"sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a",
"sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015",
"sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79",
"sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb",
"sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20",
"sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464",
"sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968",
"sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82",
"sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21",
"sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0",
"sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265",
"sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b",
"sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a",
"sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72",
"sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce",
"sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0",
"sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a",
"sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163",
"sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad",
"sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"
], ],
"index": "pypi", "index": "pypi",
"version": "==21.6b0" "version": "==22.3.0"
}, },
"click": { "click": {
"hashes": [ "hashes": [
@@ -58,144 +79,152 @@
"sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330",
"sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"
], ],
"markers": "python_version >= '3.5'", "markers": "python_version < '3.11' and python_version >= '3.7'",
"version": "==5.1.1" "version": "==5.1.1"
}, },
"executing": {
"hashes": [
"sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc",
"sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"
],
"version": "==1.2.0"
},
"flake8": { "flake8": {
"hashes": [ "hashes": [
"sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b", "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7",
"sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907" "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.9.2" "version": "==6.0.0"
}, },
"flake8-black": { "flake8-black": {
"hashes": [ "hashes": [
"sha256:941514149cb8b489cb17a4bb1cf18d84375db3b34381bb018de83509437931a0", "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34",
"sha256:f26651bc10db786c03f4093414f7c9ea982ed8a244cec323c984feeffdf4c118" "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.2.1" "version": "==0.3.6"
}, },
"flake8-commas": { "flake8-commas": {
"hashes": [ "hashes": [
"sha256:d3005899466f51380387df7151fb59afec666a0f4f4a2c6a8995b975de0f44b7", "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263",
"sha256:ee2141a3495ef9789a3894ed8802d03eff1eaaf98ce6d8653a7c573ef101935e" "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.0.0" "version": "==2.1.0"
}, },
"flake8-comprehensions": { "flake8-comprehensions": {
"hashes": [ "hashes": [
"sha256:b07aef3277623db32310aa241a1cec67212b53c1d18e767d7e26d4d83aa05bf7", "sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab",
"sha256:f24be9032587127f7a5bc6d066bf755b6e66834f694383adb8a673e229c1f559" "sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.5.0" "version": "==3.10.1"
}, },
"flake8-isort": { "flake8-isort": {
"hashes": [ "hashes": [
"sha256:2b91300f4f1926b396c2c90185844eb1a3d5ec39ea6138832d119da0a208f4d9", "sha256:537f453a660d7e903f602ecfa36136b140de279df58d02eb1b6a0c84e83c528c",
"sha256:729cd6ef9ba3659512dee337687c05d79c78e1215fdf921ed67e5fe46cce2f3c" "sha256:aa0cac02a62c7739e370ce6b9c31743edac904bae4b157274511fc8a19c75bbc"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.0.0" "version": "==6.0.0"
}, },
"flake8-quotes": { "flake8-quotes": {
"hashes": [ "hashes": [
"sha256:3f1116e985ef437c130431ac92f9b3155f8f652fda7405ac22ffdfd7a9d1055e" "sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.2.0" "version": "==3.3.2"
}, },
"greenlet": { "greenlet": {
"hashes": [ "hashes": [
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9", "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a",
"sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9", "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a",
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581", "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43",
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26", "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33",
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd", "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8",
"sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2", "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088",
"sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a", "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca",
"sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82", "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343",
"sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a", "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645",
"sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce", "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db",
"sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f", "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df",
"sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524", "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3",
"sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48", "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86",
"sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77", "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2",
"sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928", "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a",
"sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e", "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf",
"sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67", "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7",
"sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9", "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394",
"sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68", "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40",
"sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd", "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3",
"sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515", "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6",
"sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5", "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74",
"sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39", "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0",
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94", "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3",
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92", "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91",
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e", "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5",
"sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726", "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9",
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd", "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8",
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5", "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b",
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764", "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6",
"sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955", "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb",
"sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608", "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73",
"sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148", "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b",
"sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51", "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df",
"sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9", "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9",
"sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d", "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f",
"sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c", "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0",
"sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72", "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857",
"sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1", "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a",
"sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2", "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249",
"sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23", "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30",
"sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb", "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292",
"sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6", "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b",
"sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19", "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d",
"sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45", "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b",
"sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000", "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c",
"sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da", "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca",
"sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617", "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7",
"sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963", "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75",
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7", "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae",
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d", "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b",
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d", "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470",
"sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0", "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564",
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243", "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9",
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce", "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099",
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6", "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0",
"sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a", "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5",
"sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1", "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19",
"sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f", "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1",
"sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd" "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==2.0.1" "version": "==2.0.2"
}, },
"ipdb": { "ipdb": {
"hashes": [ "hashes": [
"sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5" "sha256:c23b6736f01fd4586cc2ecbebdf79a5eb454796853e1cd8f2ed3b7b91d4a3e93",
"sha256:f74c2f741c18b909eaf89f19fde973f745ac721744aa1465888ce45813b63a9c"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.13.9" "version": "==0.13.11"
}, },
"ipython": { "ipython": {
"hashes": [ "hashes": [
"sha256:55df3e0bd0f94e715abd968bedd89d4e8a7bce4bf498fb123fed4f5398fea874", "sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e",
"sha256:b5548ec5329a4bcf054a5deed5099b0f9622eb9ea51aaa7104d215fece201d8c" "sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"
], ],
"index": "pypi", "index": "pypi",
"version": "==7.31.1" "version": "==8.10.0"
}, },
"isort": { "isort": {
"hashes": [ "hashes": [
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6", "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504",
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d" "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.8.0" "version": "==5.12.0"
}, },
"jedi": { "jedi": {
"hashes": [ "hashes": [
@@ -215,10 +244,11 @@
}, },
"mccabe": { "mccabe": {
"hashes": [ "hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
], ],
"version": "==0.6.1" "markers": "python_version >= '3.6'",
"version": "==0.7.0"
}, },
"msgpack": { "msgpack": {
"hashes": [ "hashes": [
@@ -279,10 +309,11 @@
}, },
"mypy-extensions": { "mypy-extensions": {
"hashes": [ "hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
], ],
"version": "==0.4.3" "markers": "python_version >= '3.5'",
"version": "==1.0.0"
}, },
"neovim": { "neovim": {
"hashes": [ "hashes": [
@@ -301,11 +332,11 @@
}, },
"pathspec": { "pathspec": {
"hashes": [ "hashes": [
"sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6", "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229",
"sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6" "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==0.10.3" "version": "==0.11.0"
}, },
"pexpect": { "pexpect": {
"hashes": [ "hashes": [
@@ -322,6 +353,14 @@
], ],
"version": "==0.7.5" "version": "==0.7.5"
}, },
"platformdirs": {
"hashes": [
"sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9",
"sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"
],
"markers": "python_version >= '3.7'",
"version": "==3.0.0"
},
"prompt-toolkit": { "prompt-toolkit": {
"hashes": [ "hashes": [
"sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63", "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63",
@@ -337,29 +376,36 @@
], ],
"version": "==0.7.0" "version": "==0.7.0"
}, },
"pure-eval": {
"hashes": [
"sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350",
"sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"
],
"version": "==0.2.2"
},
"pycodestyle": { "pycodestyle": {
"hashes": [ "hashes": [
"sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068", "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
"sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef" "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '3.6'",
"version": "==2.7.0" "version": "==2.10.0"
}, },
"pyflakes": { "pyflakes": {
"hashes": [ "hashes": [
"sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3", "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf",
"sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db" "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '3.6'",
"version": "==2.3.1" "version": "==3.0.1"
}, },
"pygments": { "pygments": {
"hashes": [ "hashes": [
"sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1", "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297",
"sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42" "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2.13.0" "version": "==2.14.0"
}, },
"pynvim": { "pynvim": {
"hashes": [ "hashes": [
@@ -384,129 +430,27 @@
}, },
"python-dotenv": { "python-dotenv": {
"hashes": [ "hashes": [
"sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5", "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
"sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045" "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==0.21.0" "version": "==0.21.1"
}, },
"python-magic": { "python-magic": {
"hashes": [ "hashes": [
"sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626", "sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b",
"sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf" "sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.4.24" "version": "==0.4.27"
},
"regex": {
"hashes": [
"sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad",
"sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4",
"sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd",
"sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc",
"sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d",
"sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066",
"sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec",
"sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9",
"sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e",
"sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8",
"sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e",
"sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783",
"sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6",
"sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1",
"sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c",
"sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4",
"sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1",
"sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1",
"sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7",
"sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8",
"sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe",
"sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d",
"sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b",
"sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8",
"sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c",
"sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af",
"sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49",
"sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714",
"sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542",
"sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318",
"sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e",
"sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5",
"sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc",
"sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144",
"sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453",
"sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5",
"sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61",
"sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11",
"sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a",
"sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54",
"sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73",
"sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc",
"sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347",
"sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c",
"sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66",
"sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c",
"sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93",
"sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443",
"sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc",
"sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1",
"sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892",
"sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8",
"sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001",
"sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa",
"sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90",
"sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c",
"sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0",
"sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692",
"sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4",
"sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5",
"sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690",
"sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83",
"sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66",
"sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f",
"sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f",
"sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4",
"sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee",
"sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81",
"sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95",
"sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9",
"sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff",
"sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e",
"sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5",
"sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6",
"sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7",
"sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1",
"sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394",
"sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6",
"sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742",
"sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57",
"sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b",
"sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7",
"sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b",
"sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244",
"sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af",
"sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185",
"sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8",
"sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"
],
"markers": "python_version >= '3.6'",
"version": "==2022.10.31"
}, },
"s3cmd": { "s3cmd": {
"hashes": [ "hashes": [
"sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa", "sha256:15330776e7ff993d8ae0ac213bf896f210719e9b91445f5f7626a8fa7e74e30b",
"sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03" "sha256:2204306742c33c24fbca02b78e059bacfc1bfc04af09c7e9866f267a11a9ddb2"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.1.0" "version": "==2.3.0"
},
"setuptools": {
"hashes": [
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
],
"index": "pypi",
"version": "==65.5.1"
}, },
"six": { "six": {
"hashes": [ "hashes": [
@@ -516,35 +460,35 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0" "version": "==1.16.0"
}, },
"testfixtures": { "stack-data": {
"hashes": [ "hashes": [
"sha256:02dae883f567f5b70fd3ad3c9eefb95912e78ac90be6c7444b5e2f46bf572c84", "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815",
"sha256:7de200e24f50a4a5d6da7019fb1197aaf5abd475efb2ec2422fdcf2f2eb98c1d" "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"
], ],
"version": "==6.18.5" "version": "==0.6.2"
}, },
"toml": { "tomli": {
"hashes": [ "hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
], ],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version < '3.11'",
"version": "==0.10.2" "version": "==2.0.1"
}, },
"traitlets": { "traitlets": {
"hashes": [ "hashes": [
"sha256:6cc57d6dc28c85d5365961726ffd19b538739347749e13ebe34e03323a0e8f84", "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8",
"sha256:c864831efa0ba6576d09b44884b34e41defc18c0d7e720b4a2d6698c842cab3e" "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==5.8.0" "version": "==5.9.0"
}, },
"wcwidth": { "wcwidth": {
"hashes": [ "hashes": [
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e",
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"
], ],
"version": "==0.2.5" "version": "==0.2.6"
} }
} }
} }

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
# ANAVI Macro Pad 12
ANAVI Macro Pad 12 is an open source, programmable mechanical keyboard with 9 hot-swappable mechanical switches, RGB WS2812B underlighting and yellow backlit a rotary encoder and [Seeed XIAO RP2040](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html).
ANAVI Macro Pad 12 has been designed with the cross platform and open source electronics design automation suite KiCad. All KiCad [files and schematics are available at GitHub](https://github.com/anavitechnology/anavi-macro-pad-12) under [Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/).
Extensions enabled by default:
- [Encoder](/docs/en/encoder.md) Twist control for all the things
- [LED](/docs/en/led.md) Light your keys up (for backlit)
- [RGB](/docs/en/rgb.md) Light it up (for underlighting)
- [MediaKeys](/docs/en/media_keys.md) Control volume and other media functions
- [PEG_OLED](/docs/peg_oled_display.md) Show information on the mini OLED display

View File

@@ -0,0 +1,97 @@
import board
from kmk.extensions.LED import LED
from kmk.extensions.media_keys import MediaKeys
from kmk.extensions.peg_oled_Display import (
Oled,
OledData,
OledDisplayMode,
OledReactionType,
)
from kmk.extensions.RGB import RGB, AnimationModes
from kmk.keys import KC
from kmk.kmk_keyboard import KMKKeyboard
from kmk.scanners import DiodeOrientation
keyboard = KMKKeyboard()
# I2C pins for the mini OLED display
keyboard.SCL = board.D5
keyboard.SDA = board.D4
oled_ext = Oled(
OledData(
corner_one={0: OledReactionType.STATIC, 1: ['ANAVI Macro Pad 12']},
corner_two={0: OledReactionType.STATIC, 1: [' ']},
corner_three={0: OledReactionType.STATIC, 1: ['Open Source']},
corner_four={0: OledReactionType.STATIC, 1: [' ']},
),
oWidth=128,
oHeight=64,
toDisplay=OledDisplayMode.TXT,
flip=False,
)
keyboard.extensions.append(oled_ext)
led_ext = LED(
led_pin=[
board.D0,
],
brightness=100,
brightness_step=5,
brightness_limit=100,
breathe_center=1.5,
animation_mode=AnimationModes.STATIC,
animation_speed=1,
user_animation=None,
val=100,
)
keyboard.extensions.append(led_ext)
# WS2812B LED strips on the back
underglow = RGB(
pixel_pin=board.D10,
num_pixels=6,
val_limit=100,
val_default=25,
animation_mode=AnimationModes.RAINBOW,
)
keyboard.extensions.append(underglow)
# Neopixel on XIAO RP2040
frontglow = RGB(
pixel_pin=board.NEOPIXEL,
num_pixels=1,
val_limit=100,
val_default=25,
animation_mode=AnimationModes.RAINBOW,
)
keyboard.extensions.append(frontglow)
keyboard.col_pins = (board.D6, board.D8, board.D9)
keyboard.row_pins = (board.D1, board.D2, board.D3, board.D7)
keyboard.diode_orientation = DiodeOrientation.COL2ROW
media_keys = MediaKeys()
keyboard.extensions.append(media_keys)
# Matrix 4x3 keymap, 12 keys in total
keyboard.keymap = [
[
KC.N1,
KC.N2,
KC.N3,
KC.N4,
KC.N5,
KC.N6,
KC.N7,
KC.N8,
KC.N9,
KC.N0,
KC.A,
KC.B,
]
]
if __name__ == '__main__':
keyboard.go()

3
boot.py Executable file → Normal file
View File

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

0
compiled/.gitkeep Normal file
View File

7
docker-compose.yml Normal file
View File

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

14
docker_mpy_build.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/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,8 +76,10 @@ 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) In case you need it, debugging help can be found [here](debugging.md)
If you need support with KMK or just want to say hi, find us in For asynchronous support and chatter about KMK, [join our Zulip
[#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is community](https://kmkfw.zulipchat.com)!
bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
for convenience. If you ask for help in chat or open a bug report, if possible If you ask for help in chat or open a bug report, if possible
make sure your copy of KMK is up-to-date. make sure your copy of KMK is up-to-date.
In particular, swing by the Zulip chat *before* opening a GitHub Issue about
configuration, documentation, etc. concerns.

View File

@@ -6,8 +6,7 @@ to make contributing as easy as possible for everyone while maintaining a consis
## Contributing Code ## Contributing Code
The following guidelines should ensure that any code contributed can be merged in as The following guidelines should ensure that any code contributed can be merged in as
painlessly as possible. If you're unsure how to set up your development environment, painlessly as possible. If you're unsure how to set up your development environment,
feel free to join the chat, [#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). feel free to [join our Zulip community](https://kmkfw.zulipchat.com).
This channel is bridged to Discord [here](https://discord.gg/QBHUUpeGUd) for convenience.
### Code Style ### Code Style

View File

@@ -1,6 +1,7 @@
# Stringy Keymaps # Stringy Keymaps
Enables referring to keys by `'NAME'` rather than `KC.NAME`. Enables referring to keys by `'NAME'` rather than `KC.NAME`.\
This extension allows for a seamless integration of both string-based key references and standard keycodes.
For example: For example:
@@ -13,6 +14,9 @@ from kmk.extensions.stringy_keymaps import StringyKeymaps
# Indexed # Indexed
# keyboard.keymap = [[ KC['A'], KC['B'], KC['RESET'] ]] # keyboard.keymap = [[ KC['A'], KC['B'], KC['RESET'] ]]
# String names mixed with normal keycodes
# keyboard.keymap = [[ 'A' , KC.B, KC.RESET ]]
# String names # String names
keyboard.keymap = [[ 'A' , 'B', 'RESET' ]] keyboard.keymap = [[ 'A' , 'B', 'RESET' ]]
@@ -27,3 +31,5 @@ keyboard.extensions.append(stringyKeymaps)
It should be noted that these are **not** ASCII. The string is **not** what It should be noted that these are **not** ASCII. The string is **not** what
will be sent to the computer. The examples above have no functional difference. will be sent to the computer. The examples above have no functional difference.
When utilizing argumented keys, such as `KC.MO(layer)`, it's not possible to use a string like `'MO(layer)'` instead employ the standard notation of e.g. `KC.MO(1)` in your keymap.

View File

@@ -9,9 +9,7 @@ Linux).
Given `make` and `rsync` are available on your system (in `$PATH`), the Given `make` and `rsync` are available on your system (in `$PATH`), the
following will copy the `kmk` tree to your CircuitPython device, and will copy following will copy the `kmk` tree to your CircuitPython device, and will copy
the file defined as `USER_KEYMAP` as your `main.py`. It will also copy our the file defined as `USER_KEYMAP` as your `main.py`. It will also copy our
`boot.py`, which allocates a larger stack size (simply - more of the device's `boot.py`. If any of these files exist on your CircuitPython device already, they
RAM will be available to KMK and your keyboard config) than CircuitPython's
default. If any of these files exist on your CircuitPython device already, they
will be overwritten without a prompt. will be overwritten without a prompt.
If you get permissions errors here, **don't run make as root or with sudo**. See If you get permissions errors here, **don't run make as root or with sudo**. See

View File

@@ -1,9 +1,9 @@
# Support # Support
If you need support with KMK or just want to say hi, find us in [#kmkfw:klar.sh For asynchronous support and chatter about KMK, [join our Zulip
on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is bridged to community](https://kmkfw.zulipchat.com)!
Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
for convenience.
If you ask for help in chat or open a bug report, if possible If you ask for help in chat or open a bug report, if possible
make sure your copy of KMK is up-to-date. make sure your copy of KMK is up-to-date.
In particular, swing by the Zulip chat *before* opening a GitHub Issue about
configuration, documentation, etc. concerns.

View File

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

View File

@@ -123,8 +123,6 @@ usuários](https://github.com/KMKfw/user_keymaps) que fornecemos e fuce nossa
Caso precise, ajuda para depuração pode ser encontrada [aqui](debugging.md). Caso precise, ajuda para depuração pode ser encontrada [aqui](debugging.md).
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal canal [kmkfw no Zulip](https://kmkfw.zulipchat.com).
tem uma ponte no Discord Se você precisa de ajuda ou pretende abrir um bug report, se
[aqui](https://discordapp.com/widget?id=493256121075761173&theme=dark) por
conveniência. Se você precisa de ajuda ou pretende abrir um bug report, se
possível se possível, verifique se sua cópia do KMK está atualizada. possível se possível, verifique se sua cópia do KMK está atualizada.

View File

@@ -1,10 +1,7 @@
# Suporte # Suporte
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal canal [no Zulip](https://kmkfw.zulipchat.com).
tem uma ponte no Discord
[aqui](https://discordapp.com/widget?id=493256121075761173&theme=dark) por
conveniência.
Se você precisa de ajuda ou pretende abrir um bug report, se Se você precisa de ajuda ou pretende abrir um bug report, se
possível se possível, verifique se sua cópia do KMK está atualizada. possível se possível, verifique se sua cópia do KMK está atualizada.

View File

@@ -127,3 +127,13 @@ def ble_refresh(key, keyboard, *args, **kwargs):
keyboard._hid_helper.stop_advertising() keyboard._hid_helper.stop_advertising()
keyboard._hid_helper.start_advertising() keyboard._hid_helper.start_advertising()
return keyboard return keyboard
def ble_disconnect(key, keyboard, *args, **kwargs):
from kmk.hid import HIDModes
if keyboard.hid_type != HIDModes.BLE:
return keyboard
keyboard._hid_helper.clear_bonds()
return keyboard

View File

@@ -4,7 +4,8 @@ from micropython import const
from storage import getmount from storage import getmount
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey, MouseKey
from kmk.utils import clamp
try: try:
from adafruit_ble import BLERadio from adafruit_ble import BLERadio
@@ -68,6 +69,14 @@ class AbstractHID:
self.report_mods = memoryview(self._evt)[1:2] self.report_mods = memoryview(self._evt)[1:2]
self.report_non_mods = memoryview(self._evt)[3:] self.report_non_mods = memoryview(self._evt)[3:]
self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
self._cc_report[0] = HIDReportTypes.CONSUMER
self._cc_pending = False
self._pd_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
self._pd_report[0] = HIDReportTypes.MOUSE
self._pd_pending = False
self.post_init() self.post_init()
def __repr__(self): def __repr__(self):
@@ -76,47 +85,27 @@ class AbstractHID:
def post_init(self): def post_init(self):
pass pass
def create_report(self, keys_pressed): def create_report(self, keys_pressed, axes):
self.clear_all() self.clear_all()
consumer_key = None
for key in keys_pressed: for key in keys_pressed:
if isinstance(key, ConsumerKey): if key.code >= FIRST_KMK_INTERNAL_KEY:
consumer_key = key continue
break
reporting_device = self.report_device[0] if isinstance(key, ModifierKey):
needed_reporting_device = HIDReportTypes.KEYBOARD 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)
if consumer_key: for axis in axes:
needed_reporting_device = HIDReportTypes.CONSUMER self.move_axis(axis)
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)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
return self
def hid_send(self, evt): def hid_send(self, evt):
# Don't raise a NotImplementedError so this can serve as our "dummy" HID # Don't raise a NotImplementedError so this can serve as our "dummy" HID
@@ -131,12 +120,24 @@ class AbstractHID:
self._prev_evt[:] = self._evt self._prev_evt[:] = self._evt
self.hid_send(self._evt) self.hid_send(self._evt)
if self._cc_pending:
self.hid_send(self._cc_report)
self._cc_pending = False
if self._pd_pending:
self.hid_send(self._pd_report)
self._pd_pending = False
return self return self
def clear_all(self): def clear_all(self):
for idx, _ in enumerate(self.report_keys): for idx, _ in enumerate(self.report_keys):
self.report_keys[idx] = 0x00 self.report_keys[idx] = 0x00
self.remove_cc()
self.remove_pd()
self.clear_axis()
return self return self
def clear_non_modifiers(self): def clear_non_modifiers(self):
@@ -175,9 +176,6 @@ class AbstractHID:
where_to_place = self.report_non_mods where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place): for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == 0x00: if where_to_place[idx] == 0x00:
where_to_place[idx] = key.code where_to_place[idx] = key.code
@@ -193,15 +191,44 @@ class AbstractHID:
def remove_key(self, key): def remove_key(self, key):
where_to_place = self.report_non_mods where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place): for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == key.code: if where_to_place[idx] == key.code:
where_to_place[idx] = 0x00 where_to_place[idx] = 0x00
return self return self
def add_cc(self, cc):
# Add (or write over) consumer control report. There can only be one CC
# active at any time.
memoryview(self._cc_report)[1:3] = cc.code.to_bytes(2, 'little')
self._cc_pending = True
def remove_cc(self):
# Remove consumer control report.
report = memoryview(self._cc_report)[1:3]
if report != b'\x00\x00':
report[:] = b'\x00\x00'
self._cc_pending = True
def add_pd(self, key):
self._pd_report[1] |= key.code
self._pd_pending = True
def remove_pd(self):
if self._pd_report[1]:
self._pd_pending = True
self._pd_report[1] = 0x00
def move_axis(self, axis):
delta = clamp(axis.delta, -127, 127)
axis.delta -= delta
self._pd_report[axis.code + 2] = 0xFF & delta
self._pd_pending = True
def clear_axis(self):
for idx in range(2, len(self._pd_report)):
self._pd_report[idx] = 0x00
class USBHID(AbstractHID): class USBHID(AbstractHID):
REPORT_BYTES = 9 REPORT_BYTES = 9

View File

@@ -20,6 +20,7 @@ class KeyType:
SIMPLE = const(0) SIMPLE = const(0)
MODIFIER = const(1) MODIFIER = const(1)
CONSUMER = const(2) CONSUMER = const(2)
MOUSE = const(3)
FIRST_KMK_INTERNAL_KEY = const(1000) FIRST_KMK_INTERNAL_KEY = const(1000)
@@ -33,6 +34,29 @@ ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
debug = Debug(__name__) debug = Debug(__name__)
class Axis:
def __init__(self, code: int) -> None:
self.code = code
self.delta = 0
def __repr__(self) -> str:
return f'Axis(code={self.code}, delta={self.delta})'
def move(self, keyboard: Keyboard, delta: int):
self.delta += delta
if self.delta:
keyboard.axes.add(self)
keyboard.hid_pending = True
else:
keyboard.axes.discard(self)
class AX:
W = Axis(2)
X = Axis(0)
Y = Axis(1)
def maybe_make_key( def maybe_make_key(
code: Optional[int], code: Optional[int],
names: Tuple[str, ...], names: Tuple[str, ...],
@@ -340,6 +364,7 @@ def maybe_make_unicode_key(candidate: str) -> Optional[Key]:
def maybe_make_firmware_key(candidate: str) -> Optional[Key]: def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
keys = ( keys = (
((('BLE_REFRESH',), handlers.ble_refresh)), ((('BLE_REFRESH',), handlers.ble_refresh)),
((('BLE_DISCONNECT',), handlers.ble_disconnect)),
((('BOOTLOADER',), handlers.bootloader)), ((('BOOTLOADER',), handlers.bootloader)),
((('DEBUG', 'DBG'), handlers.debug_pressed)), ((('DEBUG', 'DBG'), handlers.debug_pressed)),
((('HID_SWITCH', 'HID'), handlers.hid_switch)), ((('HID_SWITCH', 'HID'), handlers.hid_switch)),
@@ -400,43 +425,62 @@ KEY_GENERATORS = (
class KeyAttrDict: class KeyAttrDict:
__cache = {} # Instead of relying on the uncontrollable availability of a big chunk of
# contiguous memory for key caching, we can manually fragment the cache into
# reasonably small partitions. The partition size is chosen from the magic
# values of CPs hash allocation sizes.
# (https://github.com/adafruit/circuitpython/blob/main/py/map.c, 2023-02)
__partition_size = 37
__cache = [{}]
def __iter__(self): def __iter__(self):
return self.__cache.__iter__() for partition in self.__cache:
for name in partition.__iter__():
yield name
def __setitem__(self, key: str, value: Key): def __setitem__(self, name: str, key: Key):
self.__cache.__setitem__(key, value) # Overwrite existing reference.
for partition in self.__cache:
if name in partition:
partition[name] = key
return key
def __getattr__(self, key: Key): # Insert new reference.
return self.__getitem__(key) if len(self.__cache[-1]) >= self.__partition_size:
self.__cache.append({})
self.__cache[-1][name] = key
return key
def get(self, key: Key, default: Optional[Key] = None): def __getattr__(self, name: str):
return self.__getitem__(name)
def get(self, name: str, default: Optional[Key] = None):
try: try:
return self.__getitem__(key) return self.__getitem__(name)
except Exception: except Exception:
return default return default
def clear(self): def clear(self):
self.__cache.clear() self.__cache.clear()
self.__cache.append({})
def __getitem__(self, key: Key): def __getitem__(self, name: str):
try: for partition in self.__cache:
return self.__cache[key] if name in partition:
except KeyError: return partition[name]
pass
for func in KEY_GENERATORS: for func in KEY_GENERATORS:
maybe_key = func(key) maybe_key = func(name)
if maybe_key: if maybe_key:
break break
else:
raise ValueError(f'Invalid key: {key}') if not maybe_key:
raise ValueError(f'Invalid key: {name}')
if debug.enabled: if debug.enabled:
debug(f'{key}: {maybe_key}') debug(f'{name}: {maybe_key}')
return self.__cache[key] return maybe_key
# Global state, will be filled in throughout this file, and # Global state, will be filled in throughout this file, and
@@ -669,6 +713,10 @@ class ConsumerKey(Key):
pass pass
class MouseKey(Key):
pass
def make_key( def make_key(
code: Optional[int] = None, code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA names: Tuple[str, ...] = tuple(), # NOQA
@@ -699,6 +747,8 @@ def make_key(
constructor = ModifierKey constructor = ModifierKey
elif type == KeyType.CONSUMER: elif type == KeyType.CONSUMER:
constructor = ConsumerKey constructor = ConsumerKey
elif type == KeyType.MOUSE:
constructor = MouseKey
else: else:
raise ValueError('Unrecognized key type') raise ValueError('Unrecognized key type')
@@ -731,6 +781,10 @@ def make_consumer_key(*args, **kwargs) -> Key:
return make_key(*args, **kwargs, type=KeyType.CONSUMER) return make_key(*args, **kwargs, type=KeyType.CONSUMER)
def make_mouse_key(*args, **kwargs) -> Key:
return make_key(*args, **kwargs, type=KeyType.MOUSE)
# Argumented keys are implicitly internal, so auto-gen of code # Argumented keys are implicitly internal, so auto-gen of code
# is almost certainly the best plan here # is almost certainly the best plan here
def make_argumented_key( def make_argumented_key(

View File

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

View File

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

View File

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

View File

@@ -114,17 +114,15 @@ class Layers(HoldTap):
''' '''
As MO(layer) but with mod active As MO(layer) but with mod active
''' '''
keyboard.hid_pending = True
# Sets the timer start and acts like MO otherwise # Sets the timer start and acts like MO otherwise
keyboard.keys_pressed.add(key.meta.kc) keyboard.add_key(key.meta.kc)
self._mo_pressed(key, keyboard, *args, **kwargs) self._mo_pressed(key, keyboard, *args, **kwargs)
def _lm_released(self, key, keyboard, *args, **kwargs): def _lm_released(self, key, keyboard, *args, **kwargs):
''' '''
As MO(layer) but with mod active As MO(layer) but with mod active
''' '''
keyboard.hid_pending = True keyboard.remove_key(key.meta.kc)
keyboard.keys_pressed.discard(key.meta.kc)
self._mo_released(key, keyboard, *args, **kwargs) self._mo_released(key, keyboard, *args, **kwargs)
def _tg_pressed(self, key, keyboard, *args, **kwargs): def _tg_pressed(self, key, keyboard, *args, **kwargs):

View File

@@ -1,7 +1,6 @@
from supervisor import ticks_ms
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
from kmk.keys import make_key from kmk.keys import AX, make_key, make_mouse_key
from kmk.kmktime import PeriodicTimer
from kmk.modules import Module from kmk.modules import Module
@@ -24,31 +23,28 @@ class PointingDevice:
class MouseKeys(Module): class MouseKeys(Module):
def __init__(self): def __init__(self):
self.pointing_device = PointingDevice()
self._nav_key_activated = 0 self._nav_key_activated = 0
self._up_activated = False self._up_activated = False
self._down_activated = False self._down_activated = False
self._left_activated = False self._left_activated = False
self._right_activated = False self._right_activated = False
self._mw_up_activated = False
self._mw_down_activated = False
self.max_speed = 10 self.max_speed = 10
self.ac_interval = 100 # Delta ms to apply acceleration self.acc_interval = 10 # Delta ms to apply acceleration
self._next_interval = 0 # Time for next tick interval
self.move_step = 1 self.move_step = 1
make_key( make_mouse_key(
names=('MB_LMB',), names=('MB_LMB',),
on_press=self._mb_lmb_press, code=1,
on_release=self._mb_lmb_release,
) )
make_key( make_mouse_key(
names=('MB_MMB',), names=('MB_MMB',),
on_press=self._mb_mmb_press, code=4,
on_release=self._mb_mmb_release,
) )
make_key( make_mouse_key(
names=('MB_RMB',), names=('MB_RMB',),
on_press=self._mb_rmb_press, code=2,
on_release=self._mb_rmb_release,
) )
make_key( make_key(
names=('MW_UP',), names=('MW_UP',),
@@ -94,38 +90,33 @@ class MouseKeys(Module):
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):
return self._timer = PeriodicTimer(self.acc_interval)
def matrix_detected_press(self, keyboard):
return keyboard.matrix_update is None
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard):
return return
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard):
if not self._timer.tick():
return
if self._nav_key_activated: if self._nav_key_activated:
if self._next_interval <= ticks_ms(): if self.move_step < self.max_speed:
# print("hello: ") self.move_step = self.move_step + 1
# 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: if self._right_activated:
self.pointing_device.report_x[0] = self.move_step AX.X.move(keyboard, self.move_step)
if self._left_activated: if self._left_activated:
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step) AX.X.move(keyboard, -self.move_step)
if self._up_activated: if self._up_activated:
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step) AX.Y.move(keyboard, -self.move_step)
if self._down_activated: if self._down_activated:
self.pointing_device.report_y[0] = self.move_step AX.Y.move(keyboard, self.move_step)
self.pointing_device.hid_pending = True
return if self._mw_up_activated:
AX.W.move(keyboard, 1)
if self._mw_down_activated:
AX.W.move(keyboard, -1)
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard):
if self.pointing_device.hid_pending and keyboard._hid_send_enabled:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self.pointing_device.hid_pending = False
return return
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard):
@@ -137,50 +128,21 @@ class MouseKeys(Module):
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard):
return return
def _mb_lmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_LMB
self.pointing_device.hid_pending = True
def _mb_lmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_LMB
self.pointing_device.hid_pending = True
def _mb_mmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_MMB
self.pointing_device.hid_pending = True
def _mb_mmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_MMB
self.pointing_device.hid_pending = True
def _mb_rmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_RMB
self.pointing_device.hid_pending = True
def _mb_rmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_RMB
self.pointing_device.hid_pending = True
def _mw_up_press(self, key, keyboard, *args, **kwargs): def _mw_up_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.report_w[0] = self.move_step self._mw_up_activated = True
self.pointing_device.hid_pending = True
def _mw_up_release(self, key, keyboard, *args, **kwargs): def _mw_up_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.report_w[0] = 0 self._mw_up_activated = False
self.pointing_device.hid_pending = True
def _mw_down_press(self, key, keyboard, *args, **kwargs): def _mw_down_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.report_w[0] = 0xFF self._mw_down_activated = True
self.pointing_device.hid_pending = True
def _mw_down_release(self, key, keyboard, *args, **kwargs): def _mw_down_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.report_w[0] = 0 self._mw_down_activated = False
self.pointing_device.hid_pending = True
# Mouse movement # Mouse movement
def _reset_next_interval(self): def _reset_next_interval(self):
if self._nav_key_activated == 1: if self._nav_key_activated == 1:
self._next_interval = ticks_ms() + self.ac_interval
self.move_step = 1 self.move_step = 1
def _check_last(self): def _check_last(self):
@@ -191,56 +153,38 @@ class MouseKeys(Module):
self._nav_key_activated += 1 self._nav_key_activated += 1
self._reset_next_interval() self._reset_next_interval()
self._up_activated = True self._up_activated = True
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
self.pointing_device.hid_pending = True
def _ms_up_release(self, key, keyboard, *args, **kwargs): def _ms_up_release(self, key, keyboard, *args, **kwargs):
self._up_activated = False self._up_activated = False
self._nav_key_activated -= 1 self._nav_key_activated -= 1
self._check_last() self._check_last()
self.pointing_device.report_y[0] = 0
self.pointing_device.hid_pending = False
def _ms_down_press(self, key, keyboard, *args, **kwargs): def _ms_down_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1 self._nav_key_activated += 1
self._reset_next_interval() self._reset_next_interval()
self._down_activated = True self._down_activated = True
# if not self.x_activated and not self.y_activated:
# self.next_interval = ticks_ms() + self.ac_intervalle
self.pointing_device.report_y[0] = self.move_step
self.pointing_device.hid_pending = True
def _ms_down_release(self, key, keyboard, *args, **kwargs): def _ms_down_release(self, key, keyboard, *args, **kwargs):
self._down_activated = False self._down_activated = False
self._nav_key_activated -= 1 self._nav_key_activated -= 1
self._check_last() self._check_last()
self.pointing_device.report_y[0] = 0
self.pointing_device.hid_pending = False
def _ms_left_press(self, key, keyboard, *args, **kwargs): def _ms_left_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1 self._nav_key_activated += 1
self._reset_next_interval() self._reset_next_interval()
self._left_activated = True self._left_activated = True
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
self.pointing_device.hid_pending = True
def _ms_left_release(self, key, keyboard, *args, **kwargs): def _ms_left_release(self, key, keyboard, *args, **kwargs):
self._nav_key_activated -= 1 self._nav_key_activated -= 1
self._left_activated = False self._left_activated = False
self._check_last() self._check_last()
self.pointing_device.report_x[0] = 0
self.pointing_device.hid_pending = False
def _ms_right_press(self, key, keyboard, *args, **kwargs): def _ms_right_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1 self._nav_key_activated += 1
self._reset_next_interval() self._reset_next_interval()
self._right_activated = True self._right_activated = True
self.pointing_device.report_x[0] = self.move_step
self.pointing_device.hid_pending = True
def _ms_right_release(self, key, keyboard, *args, **kwargs): def _ms_right_release(self, key, keyboard, *args, **kwargs):
self._nav_key_activated -= 1 self._nav_key_activated -= 1
self._right_activated = False self._right_activated = False
self._check_last() self._check_last()
self.pointing_device.report_x[0] = 0
self.pointing_device.hid_pending = False

View File

@@ -7,10 +7,9 @@ from micropython import const
import math import math
import struct import struct
from kmk.keys import make_argumented_key, make_key from kmk.keys import AX, KC, make_argumented_key, make_key
from kmk.kmktime import PeriodicTimer from kmk.kmktime import PeriodicTimer
from kmk.modules import Module from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice
I2C_ADDRESS = 0x0A I2C_ADDRESS = 0x0A
I2C_ADDRESS_ALTERNATIVE = 0x0B I2C_ADDRESS_ALTERNATIVE = 0x0B
@@ -78,29 +77,16 @@ class TrackballHandler:
class PointingHandler(TrackballHandler): class PointingHandler(TrackballHandler):
def handle(self, keyboard, trackball, x, y, switch, state): def handle(self, keyboard, trackball, x, y, switch, state):
if x > 0: if x:
trackball.pointing_device.report_x[0] = x AX.X.move(keyboard, x)
elif x < 0: if y:
trackball.pointing_device.report_x[0] = 0xFF & x AX.Y.move(keyboard, y)
if y > 0:
trackball.pointing_device.report_y[0] = y
elif y < 0:
trackball.pointing_device.report_y[0] = 0xFF & y
if x != 0 or y != 0:
trackball.pointing_device.hid_pending = True
if switch == 1: # Button pressed if switch == 1: # Button pressed
trackball.pointing_device.button_status[ keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
0
] |= trackball.pointing_device.MB_LMB
trackball.pointing_device.hid_pending = True
if not state and trackball.previous_state is True: # Button released if not state and trackball.previous_state is True: # Button released
trackball.pointing_device.button_status[ keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
0
] &= ~trackball.pointing_device.MB_LMB
trackball.pointing_device.hid_pending = True
trackball.previous_state = state trackball.previous_state = state
@@ -114,17 +100,13 @@ class ScrollHandler(TrackballHandler):
y = -y y = -y
if y != 0: if y != 0:
pointing_device = trackball.pointing_device AX.W.move(keyboard, y)
pointing_device.report_w[0] = 0xFF & y
pointing_device.hid_pending = True
if switch == 1: # Button pressed if switch == 1: # Button pressed
pointing_device.button_status[0] |= pointing_device.MB_LMB keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
pointing_device.hid_pending = True
if not state and trackball.previous_state is True: # Button released if not state and trackball.previous_state is True: # Button released
pointing_device.button_status[0] &= ~pointing_device.MB_LMB keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
pointing_device.hid_pending = True
trackball.previous_state = state trackball.previous_state = state
@@ -185,7 +167,6 @@ class Trackball(Module):
self._i2c_address = address self._i2c_address = address
self._i2c_bus = i2c self._i2c_bus = i2c
self.pointing_device = PointingDevice()
self.mode = mode self.mode = mode
self.previous_state = False # click state self.previous_state = False # click state
self.handlers = handlers self.handlers = handlers
@@ -234,9 +215,6 @@ class Trackball(Module):
return return
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard):
if self.pointing_device.hid_pending:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self._clear_pending_hid()
return return
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard):
@@ -280,13 +258,6 @@ class Trackball(Module):
next_index = 0 next_index = 0
self.activate_handler(next_index) self.activate_handler(next_index)
def _clear_pending_hid(self):
self.pointing_device.hid_pending = False
self.pointing_device.report_x[0] = 0
self.pointing_device.report_y[0] = 0
self.pointing_device.report_w[0] = 0
self.pointing_device.button_status[0] = 0
def _read_raw_state(self): def _read_raw_state(self):
'''Read up, down, left, right and switch data from trackball.''' '''Read up, down, left, right and switch data from trackball.'''
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5) left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)

39
kmk_python_Dockerfile Normal file
View File

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

BIN
mpy-cross-7 Executable file

Binary file not shown.

BIN
mpy-cross-8 Executable file

Binary file not shown.