Clackety Keyboards Powered by Python

Overview

KMK: Clackety Keyboards Powered by Python

GitHubGitHub contributorsDiscordLines of codeGitHub issuesGitHub closed issues

KMK is a feature-rich and beginner-friendly firmware for computer keyboards written and configured in CircuitPython. KMK is currently in public beta, however should handle most workflows without major issues.

If you need support with KMK or just want to say hi, find us in #kmkfw:klar.sh on Matrix. This channel is bridged to Discord here for convenience.

Features

Getting Started

Our getting started guide can be found here

The KMK Team

KMK is primarily written and maintained by @klardotsh and @kdb424, but contributions are welcome from all, whether it's in the form of code, documentation, hardware designs, feature ideas, or anything else that comes to mind. A list of KMK's contributors can be found on GitHub.

While Adafruit employees and affiliates are occasionally found in the commit log and their help has been crucial to KMK's success, KMK is not an official Adafruit project, and the Core team is not compensated by Adafruit for its development.

Code Style

KMK uses Black with a Python 3.6 target and, (controversially?) single quotes. Further code styling is enforced with isort and flake8 with several plugins. make fix-isort fix-formatting before a commit is a good idea, and CI will fail if inbound code does not adhere to these formatting rules. Some exceptions are found in setup.cfg loosening the rules in isolated cases, notably user_keymaps (which is also not subject to Black formatting for reasons documented in pyproject.toml).

License, Copyright, and Legal

All software in this repository is licensed under the GNU Public License, verison 3. All documentation and hardware designs are licensed under the Creative Commons Attribution-ShareAlike 4.0 license. Contributions to this repository must use these licenses unless otherwise agreed to by the Core team.

Comments
  • Status LED Support?

    Status LED Support?

    Hello,

    I've looked over the documentation and I am not seeing anything about how to configure LEDs for Caps Lock, Num Lock or Scroll lock.

    I see plenty of information on how to configure RGB leds for back-lighting and such but that isn't what I am looking for.

    Is this not a supported feature or am I just missing it somewhere?

    enhancement general firmware requires hardware testing 
    opened by Arudinne 32
  • Index and get keys

    Index and get keys

    Allow the KC collection to be accessed;

    KC.KEY_NAME KC['KEY_NAME'] KC.get('KEY_NAME')

    This will allow requesting of keys by names that aren't valid method names.

    Also, added tests to prove the keys created are the same instance, request order doesn't matter and case (where appropriate) isn't relevant. Remove code that could have caused stack overflow (recursion).

    opened by morrijr 25
  • Add support for displays

    Add support for displays

    Mainly I'm talking about I2C/SPI OLED displays but more can come later on. It's a big undertaking and these decisions have to be taken:

    • [ ] How do we abstract it?
    • [ ] How can one decide what and where is displayed?
    • [ ] How much do we optimize for screen responsiveness vs available cycles & memory (triple buffering would be SWEET)
    • [ ] What do we want to display?
      • Current status (connected/disconnected)
      • Current RGB animation/status
      • Status indicators (Caps/Scroll/Num)
      • WPM
      • Matrix scan/data sending frequencies
      • Uptime
      • Current layer
      • Active communication protocol (USB/BT)
      • Battery info
      • Time & date
      • Bluetooth info
        • Name
        • Pin for LESC
        • Selected host
        • Connected hosts
        • Paired hosts
        • Pairing status (active?)
        • Signal strength
        • LESC status
    enhancement requires hardware testing 
    opened by dzervas 24
  • Support for tap behavior autorepeat for modtap and layertap keys.

    Support for tap behavior autorepeat for modtap and layertap keys.

    This is an implementation of QMK-like autorepeat for tap-hold keys.

    Assuming you have a tap hold key, you can simulate a long press of the tap behavior (which should trigger the autorepeat feature if set in the OS). To this purpose: within the hold delay, tap the key once, then press it again and keep it pressed as long as you want the autorepeat to last. The behavior can be disabled by passing the optional argument repeat = False.

    I did not write the doc yet (what are the concerned files? only modtap.md and layers.md?)

    opened by ald0o 21
  • Use keypad.Keys module from CP7.0 to support boards with key per GPIO

    Use keypad.Keys module from CP7.0 to support boards with key per GPIO

    These changes are intended to support the Pimoroni Keybow2040 (same as #193) - a 4x4 grid with an RGB LED per key. Rather than directly modifying KMKKeyboard to accept a different matrix, I subclassed it to CustomMatrixKeyboard and overrode everything that works directly with the MatrixScanner class.

    The new scanner implements as little as possible - it's basically just a key mapping / event translation layer over the top of keypad.Keys. Implementing a proper matrix should be a fairly trivial variation on this, using keypad.KeyMatrix instead (I don't have HW to test with although I could throw something together basic pretty easily).

    My next step from here probably would be to refactor KMKKeyboard to pull everything but the MatrixScanner init code out into a common base class that we can use for the existing matrix as well as the CP7.0 keypad stuff. An extension on this would be a scanner that combines other scanners, so you could mix and match key-per-gpio and a regular matrix on a single board.

    Hell, we could even have a scanner that reads encoder events, or one that reads UART or i2c events, or... etc 😛

    (EDIT: this implements #237, despite it not being what I set out to do originally...)

    opened by eltariel 21
  • A home for asynchronous discussion about KMK

    A home for asynchronous discussion about KMK

    Hi, It would be nice to have a way to reference already asked questions. Github Discussions could be enabled on this repo with a simple settings change, as a way of organically growing the KB.

    There is a lot of good stuff going through on Matrix, but it's still a Chat-based paradigm with, most of the downsides of synchronous communications. Like difficulty finding old info, it creates pressure on user to 'Keep up', it weaves content from different threads into the same wall of text, etc.

    opened by LukeDRussell 17
  • Migrate to CircuitPython 7 Keypad APIs

    Migrate to CircuitPython 7 Keypad APIs

    Our current matrix scanner is, well, what it is. It's pure Python, it bakes in quite a few assumptions about how your keyboard looks and works (eg #192), and it cuts some interesting corners in the name of performance. Thankfully, the lovely folks at Adafruit have taken it upon themselves to support various types of matrix and non-matrix key-based input mechanisms in CircuitPython itself, with efficient and ergonomic C-backed APIs. Let's use them.

    We should decide whether to retain the old matrix scanner wholesale (@Gigahawk has alluded in Matrix that this is preferable for those using GPIO expanders, as some of them expose DigitalInOut-like objects that the C HAL can't talk to), use the existing MatrixScanner class as a stub/abstraction over the CircuitPython library (I'm not entirely sure why, other than for backwards compatibility, though the MatrixScanner isn't particularly publicly-used anyway so there should be no third-party consumers), or completely scrap the file.

    This trivializes #188 to the point that I'm just going to absorb it into this issue: when we migrate to Keypad, we should expose the KeyMatrix's interval to KMK users in a reasonably ergonomic way.

    enhancement general firmware upstream-cpy-related 
    opened by klardotsh 17
  • RFC: Shutdown of #kmkfw:klar.sh Matrix room

    RFC: Shutdown of #kmkfw:klar.sh Matrix room

    Hi everyone!

    Let's just jump right in, no big opening blurb from me this time:

    • I'm flattered and humbled by how many folks want to use KMK, and want to chat about it
    • For the past four years, I've been hosting the synchronous chat systems on my own infrastructure, using Matrix because free software needs free tools and I wasn't willing to let the Discord monoculture within the mechanical keyboard scene take another project
    • For several reasons, I am intending to gradually exit the Matrix homeserver hosting game:
      • The canonical homeserver implementation, Synapse, is extremely resource intensive
      • The alternatives, such as Dendrite, seem to be in a perpetual state of catching up, and not production-ready
      • I'm less interested in large web-scale federated IM these days, preferring small dark forests of the internet, and thus I am likely switching my personal DMs over to some other non-federated protocol (IRC, Zulip, XMPP without federation, whatever)
      • My plans next summer summarize to meaning my availability (and motivation) to do server maintenance will be limited-if-existent at all, which makes me a horrible single point of failure for an ever-growing online community

    In light of all of this, I need to make the unilateral decision to responsibly shut down the #kmkfw:klar.sh Matrix channel. What we do from here is where the discussion begins. Here are some options I've thought of. I invite the community to come up with more, and to some degree am offering @xs5871 the final decision making authority here, if they want it.

    In relative order of difficulty or disruption:

    • Find a new homeserver for the #kmkfw Matrix channel, on Matrix. This might mean the flagship instance, or some FOSS-friendly instance, or maybe even an instance hosted by someone in the community. Matrix supports room moves; we could gracefully move all users in the existing room over to the new one and leave a redirect in place for a while at the Matrix level while documentation and so forth gets updated. t2bot.io Discord bridge needs migrated to new room, and moderation permissions set up.
    • Migrate fully to the existing Discord guild, free-tools-for-free-software be damned. Remove the t2bot.io Matrix bridge, promote a new moderator in the guild on the Discord side, and life carries on like nothing happened for folks who joined on the Discord side. Matrix users who strongly oppose the privacy or freedom practices of Discord are left out to dry.
    • Move official KMK chatter to another IM protocol:
      • IRC (esper.net, oftc.net, libera.chat, etc.)
      • Zulip (disclosure: this is my employer). Can be self-hosted, or use the managed instances at Zulip Cloud, for which sponsorships are available to many FOSS projects (I have nothing to do with that process personally, I just write code here 😄)
      • XMPP (I have no idea how this ecosystem looks these days)
      • Something else?
    • Move official KMK chatter to an asynchronous protocol and shut down "official" IM entirely, which makes this issue somewhat of a sibling to #437, for which discussion is yet-ongoing. Unofficial IM rooms could of course still pop up under their own moderation rules, which could potentially even be linked from the README. This is the approach the Zig programming language uses: there are no official communication platforms other than GitHub over there, but the website links communities which follow a shared code of conduct.

    Thanks all for a great four years of KMK so far. I hope whatever we decide here (and in #437) helps set the project up for another four.

    opened by klardotsh 16
  • Add Faux Fox Keyboard from Fingerpunch.xyz

    Add Faux Fox Keyboard from Fingerpunch.xyz

    This PR includes the work done by @sadekbaroudi late last year. I've added a kb.py for the Nice Nano and my basic keymap.

    My intent was to keep Sadek's commits as is from his fork. If I've messed up the attributions with git, my apologies, I'll try to fix it.

    opened by LukeDRussell 16
  • Implement BLE HID

    Implement BLE HID

    https://github.com/adafruit/circuitpython/issues/1050 is moving courtesy of @dhalbert. We should do whatever is necessary (both within KMK and, if necessary, upstream) to support connection between a single-piece keyboard or master component of a split keyboard and a BLE host (PC, phone, whatever) as soon as is reasonable. This scope does not include communication between two halves of a keyboard over Bluetooth.

    Our HID system is fairly abstracted from the underlying implementation at this point, so a simple implemention of kmk.hid.BLE.send likely gets us most/all of the way there as far as targeting upstream's BLE libs. It is likely we'll want to split this HID implementation out of kmk.hid into an Extension assuming https://github.com/KMKfw/kmk_firmware/tree/topic-merge-keyboard-and-state (misnomer at this point; that branch implements the abstract kmk.extensions.Extension API and begins moving most non-core KMK components to use it) merges before this is worked on. We'll also need to provide workflows (how? keys? main.py interfaces?) to pair and bond the keyboard with the host; ideally we could support multiple host pairings (think similar to a Logitech K810 for easy swapping.

    enhancement official boards bluetooth/wireless 
    opened by klardotsh 16
  • Extract key generators

    Extract key generators

    This PR pulls the key test/create logic out of the KeyAttrDict::__getitem__ into a collection that is iterated over.

    This opens up the possibility of having extensions/modules/user code altering it allowing the list to be broken up resulting in potentially a smaller list.

    Reviewers: I am not by trade a Python developer. This refactor works (both tests and on my hardware). However while some of the previous code used a similar technique (and lambdas) I'm not 100% sure of any potential performance (memory or speed) issues. The testing I've done has shown no speed decrease, but I'm unable to judge potential impact to memory.

    opened by morrijr 14
  • Adding ComboLayers to Layers Module (See #658)

    Adding ComboLayers to Layers Module (See #658)

    Combo Layers

    Combo Layers is when you hold down 2 or more KC.MO() or KC.LM() keys at a time, and it goes to a defined layer.

    By default combo layers is not activated. You can activate combo layers by adding this to your main.py file. The combolayers NEEDS to be above the keyboard.modules.append(Layers(combolayers))

    combolayers = {
      (1, 2): 3,
       }
    keyboard.modules.append(Layers(combolayers))
    

    In the above code, when layer 1 and 2 are held, layer 3 will activate. If you release 1 or 2 it will go to whatever key is still being held, if both are released it goes to the default (0) layer. You should also notice that if you already have the layers Module activated, you can just add combolayers into (Layers())

    You can add more, and even add more than 2 layers at a time.

    combolayers = {
      (1, 2): 3,
      (1, 2, 3): 4,
      }
    

    Limitations

    Because of the way this feature works, you have to do the combo's in numerical order on the left side of the colon.

    Example (1, 2): 3 works. (2, 1): 3 would not work. You can on the other hand do (3, 4): 2 because the smaller number is to the right of the colon. You can't go to layer 0. so something like (1, 2): 0 doesn't work.

    Limitations with more than 2 combo layers

    Although adding more than 2 layers does work, ((1, 2, 3): 4 for example) the functionality you get where it goes to whatever layer is still being held when another key is released, doesn't work. If you release the 3rd one, it will usually go to the second key press's layer if you continue to hold. Additionally, if you do use more than one layer combo, you should put anything that has more than 2 at the bottom. for example the following

    combolayers = {
      (1, 2): 3,
      (1, 3): 4,
      (2, 3): 6,
      (1, 2, 3): 5,
      }
    

    Fully Working Example code

    Below is an example of a fully working keypad that uses combo layers.

    print("Starting")
    
    import board
    
    from kmk.kmk_keyboard import KMKKeyboard
    from kmk.keys import KC
    
    combolayers = {
      (1, 2): 3,
    keyboard.modules.append(Layers(combolayers))
    
    
    keyboard = KMKKeyboard()
    
    
    keyboard.keymap = [
        [ #Default
        KC.A,     KC.B  KC.C  KC.D,
        KC.E,     KC.F  KC.G  KC.H,
        KC.MO(1), KC.J, KC.K, KC.MO(2),
        ],
        [ #Layer 1
        KC.N1,    KC.N2, KC.N3, KC.N4,
        KC.N5,    KC.N6, KC.N7, KC.8,
        KC.MO(1), KC.N9, KC.N0, KC.MO(2),
        ],
            [ #Layer 2
        KC.EXLM,  KC.AT,   KC.HASH, KC.DLR,
        KC.PERC,  KC.CIRC, KC.AMPR, KC.ASTR,
        KC.MO(1), KC.LPRN, KC.RPRN, KC.MO(2),
        ],
            [ #Layer 3
        KC.F1,   KC.F2, KC.F3,  KC.F4,
        KC.F5,   KC.F6, KC.F7,  KC.F8,
        KC.MO(1) KC.F9, KC.F10, KC.MO(2)
        ]
        
    ]
    
    if __name__ == '__main__':
        keyboard.go()
    
    opened by doesntfazer 1
  • Add auto shift on key hold similar to QMK's auto_shift

    Add auto shift on key hold similar to QMK's auto_shift

    Add the ability to hold a key for a predetermined time to send the shifted keypress.

    https://docs.qmk.fm/#/feature_auto_shift

    The feature could be improved upon by having the ability to control auto shift enabled by layer. For example, disabling autoshift on my gaming layer where I'll need to be holding keys without them being shift modified.

    opened by CupricReki 1
  • Update layers.md

    Update layers.md

    L87 to L90

    1)the function declaration was missing the self argument, so added it.

    2)i changed the color changing method call to just changing the hue parameter of the rgb object... this works perfectly with the breathing animation

    opened by SivanSrimanPC 2
  • Reduce key dictionary memory footprint

    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.

    opened by xs5871 0
  • fix: support CircuitPython 8.0.0-beta3

    fix: support CircuitPython 8.0.0-beta3

    CircuitPython 8 changes the API of the supervisor module. This fix accounts for the old and new APIs without requiring any other configuration changes.

    Fixes https://github.com/KMKfw/kmk_firmware/issues/655

    Tested this on a pi pico with both 7.3.3 and 8.0.0-beta4.

    opened by DBendit 1
Owner
KMK Firmware
Pythonic Mechanical Keyboard Firmware
KMK Firmware
An app about keyboards, originating from the design of u/Sonnenschirm

keebapp-backend An app about keyboards, originating from the design of u/Sonnenschirm Setup Firstly, ensure that the environment for python is install

null 8 Sep 4, 2022
India's own RPA Platform Python Powered

Welcome to My-AutoPylot , Made in India with ❤️ What is My-AutoPylot? PyBots is an Indian firm based in Vadodara, Gujarat. My-AutoPylot is a product d

PyBots Pvt Ltd 28 Sep 12, 2022
An AI-powered device to stop people from stealing my packages.

Package Theft Prevention Device An AI-powered device to stop people from stealing my packages. Installation To install on a raspberry pi, clone the re

rydercalmdown 157 Nov 24, 2022
A Pythonic Data Catalog powered by Ray that brings exabyte-level scalability and fast, ACID-compliant, change-data-capture to your big data workloads.

DeltaCAT DeltaCAT is a Pythonic Data Catalog powered by Ray. Its data storage model allows you to define and manage fast, scalable, ACID-compliant dat

null 45 Oct 15, 2022
A server shell for you to play with Powered by Django + Nginx + Postgres + Bootstrap + Celery.

A server shell for you to play with Powered by Django + Nginx + Postgres + Bootstrap + Celery.

Mengting Song 1 Jan 10, 2022
📽 Streamlit application powered by a PyScaffold project setup

streamlit-demo Streamlit application powered by a PyScaffold project setup. Work in progress: The idea of this repo is to demonstrate how to package a

PyScaffold 2 Oct 10, 2022
Runtime profiler for Streamlit, powered by pyinstrument

streamlit-profiler ???? Runtime profiler for Streamlit, powered by pyinstrument. streamlit-profiler is a Streamlit component that helps you find out w

Johannes Rieke 23 Nov 30, 2022
Replite - An embeddable REPL powered by JupyterLite

replite An embeddable REPL, powered by JupyterLite. Usage To embed the code cons

Jeremy Tuloup 47 Nov 9, 2022
Pixelarticons - Pixel Art Icons made simple for Flutter, powered by pixelarticons and fontify

Pixelarticons - Pixel Art Icons made simple for Flutter, powered by pixelarticons and fontify

lask 16 Dec 12, 2022
Todos os exercícios do Curso de Python, do canal Curso em Vídeo, resolvidos em Python, Javascript, Java, C++, C# e mais...

Exercícios - CeV Oferecido por Linguagens utilizadas atualmente O que vai encontrar aqui? ?? Esse repositório é dedicado a armazenar todos os enunciad

Coding in Community 43 Nov 10, 2022
PyDy, short for Python Dynamics, is a tool kit written in the Python

PyDy, short for Python Dynamics, is a tool kit written in the Python programming language that utilizes an array of scientific programs to enable the study of multibody dynamics. The goal is to have a modular framework and eventually a physics abstraction layer which utilizes a variety of backends that can provide the user with their desired workflow

PyDy 307 Jan 1, 2023
A Python script made for the Python Discord Pixels event.

Python Discord Pixels A Python script made for the Python Discord Pixels event. Usage Create an image.png RGBA image with your pattern. Transparent pi

Stanisław Jelnicki 4 Mar 23, 2022
this is a basic python project that I made using python

this is a basic python project that I made using python. This project is only for practice because my python skills are still newbie.

Elvira Firmansyah 2 Dec 14, 2022
Analisador de strings feito em Python // String parser made in Python

Este é um analisador feito em Python, neste programa, estou estudando funções e a sua junção com "if's" e dados colocados pelo usuário. Neste código,

Dev Nasser 1 Nov 3, 2021
Python with braces. Because Python is awesome, but whitespace is awful.

Bython Python with braces. Because Python is awesome, but whitespace is awful. Bython is a Python preprosessor which translates curly brackets into in

null 1 Nov 4, 2021
PSP (Python Starter Package) is meant for those who want to start coding in python but are new to the coding scene.

Python Starter Package PSP (Python Starter Package) is meant for those who want to start coding in python, but are new to the coding scene. We include

Giter/ 1 Nov 20, 2021
Py-Parser est un parser de code python en python encore en plien dévlopement.

PY - PARSER Py-Parser est un parser de code python en python encore en plien dévlopement. Une fois achevé, il servira a de nombreux projets comme glad

pf4 3 Feb 21, 2022
A community based economy bot with python works only with python 3.7.8 as web3 requires cytoolz

A community based economy bot with python works only with python 3.7.8 as web3 requires cytoolz has some issues building with python 3.10

null 4 Jan 1, 2022