The most hackable keyboard in all the land

Related tags

MiscellaneousMiRage
Overview

MiRage Modular Keyboard

© 2021 Zack Freedman of Voidstar Lab

Licensed Creative Commons 4.0 Attribution Noncommercial Share-Alike

The MiRage is a 60% ortholinear keyboard with three clickable OLED displays, intended for Kailh Choc switches and running custom CircuitPython firmware on a Seeedstudio Xiao RP2040.

THIS PROJECT IS INCOMPLETE. DO NOT MAKE IT.

The PCB can be populated as-is for a "plank" keyboard or broken in half for a split board. The right half can be used independently as the Rage Pad numberpad/macro pad/stream deck.

This was designed for a YouTube video on my channel: https://youtu.be/Fg0V5M0llaE It will be improved and sold as a kit, and will form part of a larger project called the Fata Morgana cyberdeck.

Fusion 360 model: https://a360.co/3vEh6YI

The PCB, firmware, keymaps, and models have major issues that need to be fixed before moving forward. This project is not ready to be reproduced. Do not attempt to make it. Keymap instructions, assembly guide, BOM, and other documentation will be provided once the project is ready for release.

My component choices are final. Attempts to change my mind will be roasted in a future video.

Libraries are temporarily included for testing purposes. These will be replaced by references on release.

Keymaps are lists of bindings in the format: R[Row #], K[Key #]: [Key name (optional)] # Comments start with a hash On press: [Command(s) to perform once as soon as user presses key] On click: [Command(s) to perform when user presses and releases key within a few hundred milliseconds] On double-click: [Command(s) to perform when user presses and releases key twice within a few hundred milliseconds. The dash in 'double-click' is not optional.] On hold: [Command(s) to perform when user holds key for more than a few hundred ms. These generally repeat or remain in effect until the key is released.] On release: [Command(s) to perform once when user releases key. This is done after On Click and On Double-Click events are finished, and after ongoing On Hold events are cleaned up.]

Actions you can bind to a key or event:

  • LEFT SHIFT: Specify key bindings by naming them in all caps. You can see all the available key names in keynames.py. Key names must be in all caps. Spaces are optional. If a key is bound inline, it binds all events.
  • Click LEFT SHIFT: This key will be pressed and instantly released a single time, even if this is called by an On Hold event. Clicking a key that's already Pressed will release, press, and release it.
  • Press LEFT SHIFT: This key will be pressed indefinitely. Pressing a key that's already Pressed has no effect. Remember to add a way to release it...
  • Release LEFT SHIFT: This key will be released. No effect if the key is not Pressed.
  • CTRL + ALT + DELETE: Performs an operation on multiple keys simultaneously. You can Click, Press, Release, or straight-up bind key combos as if they were individual keys! Spaces around the plus signs are optional.
  • Switch to Numpad Layer: Invokes specified layer indefinitely. This is case-insensitive. You don't need to include the layer's extension. Make sure to read the Layer Gotchas below!
  • Leave Numpad Layer: If specified layer is currently invoked, dismisses it.
  • Switch to Numpad Layer until released: Invokes the specified layer as long as this key remains held, and dismisses it when released. Cannot be bound to On Press, On Click, On Double-Click, or On Release events. While in effect, layers above the one that defined this action do not apply to this key.
  • Toggle Numpad Layer: Acts as a Switch To action if specified layer is not currently in effect, and a Leave action if it is. Note that this can be blocked by layers above it, so make sure the new layer leaves this key open!
  • Go home: Dismisses all invoked layers.
  • Type "Hello world!": Types the specified string a single time, one letter at a time. Don't put double quotes and commas in the string! Use [DOUBLE QUOTES] and [COMMA] instead! Any necessary keys that are currently Pressed will be released, pressed, and released again.
  • Type "Hello World!" repeatedly: When bound to an On Press or On Hold event, types the string over and over. Extremely annoying.
  • wait 200ms: Blocks everything for that much time. You can specify milliseconds, seconds, or minutes, in full or using ms, msec, sec, s, m, or min. Used in command sequences.
  • Click WIN+R, wait 200ms, type "cmd", click ENTER: Sequence any combination of actions with commas. Each action is performed in its entirety before moving on. The On Hold behavior of a command sequence is not yet defined.
  • Nothing: Allows keys on upper layers to block actions on lower layers without any side effects.
  • Pass through: Sends this operation to the next lowest layer.
  • Reload keymaps: Triggers a Go Home action, then reloads all the keymaps.
  • Reset keyboard: Triggers a software reset - disconnects from PC, reloads keymaps, and reconnects.
  • Bootloader: Enters UF2 bootloader - disconnects from PC, kills CircuitPython, and reconnects as UF2 flash drive. There is no way to return from the bootloader to the code without unplugging the keyboard. This is an inbuilt limit of the bootloader and beyond my control.

Row and key numbers are zero-indexed, and refer to the physical placement of the keys on the keyboard. These have nothing to do with the schematic. It's common sense numbering Row 0, Key 0 is the top-left key.

Whitespace and line terminators are irrelevent. You can even use tabs, you sick bastard. UTF-8 encoding is strongly recommended; not sure how well Python handles bigger characters.

You can actually define the same key and same key action multiple times in the same map. This has the same effect as creating Sequences, and is extremely obnoxious to debug. I can't prevent you from doing it, but I can say "I told you so."

Layer Gotchas!

  • Each layer's name is the same as the filename of the keymap that defined it, and is case- and extension-insensitive. If multiple keymap files have the same name with different capitalization, the keyboard will crash on purpose just to spite you.
  • One layer must be called Base Layer. This is not optional. The keyboard will not boot unless there's an applicable Base Layer.
  • The Base Layer is always in effect. When another layer is invoked, it's "stacked" on top. Invoking another layer stacks it on the other layer, and so on.
  • When a key event happens, it's sent to the topmost layer. If that layer doesn't handle it, the next layer is checked, and so on. If you want the event to fall through anyways, such as in a sequence, use the Pass through action.
  • Layer-related actions DO NOT apply immediately. Instead, the system reads every key, completes every Action fired, then applies any layer actions. This makes the layer switching process more predictable if multiple keys were pressed.
  • When a layer is invoked, if it's already in the stack, it's moved to the top.
  • You cannot invoke or dismiss the Base Layer. Attempting to do so has no effect.
  • The layer(s) selected by Layer Select Widgets have special slots above the Base Layer and just below the layer stack. If multiple clicky displays have Layer Select Widgets, the top screen layer is just below the layer stack and the bottom screen layer just above the Base Layer.
  • If a layer selected by a Layer Select Widget is invoked, it moves from its special slot to the top of the stack. If it's dismissed, it returns to its special slot.
  • Folders are provided for MiRage and Rage keymaps. Only the relevant ones apply.
  • Needs to be implemented: When a layer is dismissed, if one or more keys with On Hold events defined by that layer are held, the On Hold ends. If one or more held keys have an On Release event, it's called. Pass Through actions in these events are ignored.

PCB problems to fix:

  • VDD and VSS supply pins of PCA9505 I/O expanders are reversed
  • RESET pins of PCA9505s must be pulled up
  • Choc footprints will be extended to support Cherry MX switches
  • Cut relief under microcontroller footprint for Adafruit QT PY. This part is NOT currently compatible.
  • Increase size and number of breakaway tabs
  • Right-angle headers are too far apart
  • Add at least 4 keys
  • Bottom screws are blocked by lowest row of keycaps
  • Split is shifted one row to the left from usual typing position

Enclosure problems to fix:

  • Missing holes to access BOOT and RESET buttons
  • Missing holes to view onboard LEDs
  • Cutout for USB cable is too small
  • Rubber foot relief diameter too small and prone to sagging
  • Bottom feet are too far from edges
  • A small amount of PCB text is visible - poor fit and finish
  • Magnetic applique falls off too easily
  • Plank enclosure has header relief on wrong side
  • Display buttons can crack if mashed down very hard

Code problems to fix (that I can remember off the top of my head, there are a lot)

  • Rage board not implemented (not detected or automatically switched)
  • Unplugging left side during runtime causes crash
  • Code needs to be sped up about 200%
  • Widget updating code needs to be sped up about 5000%
  • Rage keymaps are missing layer switches
  • Only key bindings can be defined inline
  • Interactions between key event bindings and inline key bindings are unspecified
  • Hold events lag, as if a click or double-click event were also bound
  • Double-clicking also fires Click event
  • Ongoing Hold events end sloppily if a layer switch overrides that binding
  • No visual feedback for syntax errors, exceptions, layer switches, modal Lock keys, etc
  • We need more widgets
  • Fallback behavior in case of keymap errors
  • Occasional failure to auto-run code on boot
  • Including a comma in a 'Type' command crashes parser
  • If a key down command is sent then a Bootloader command runs, the key is never released
  • Configuration setting is needed to redefine WINDOWS and ALT to GUI and OPTION
  • Poor performance is due to CircuitPython, not I/O expanders. These I/O expanders can be polled over 1,000 times a second. This code would be MASSIVELY slower if a matrix were used instead of I/O expanders.

Additional things to create:

  • Plank enclosure without 3.5mm plug relief
  • Split enclosure with header relief
  • Rage (right hand) enclosure without 3.5mm plug relief
  • Dashboard widget
  • Widget that interacts with desktop
  • Set typing speed
  • Enable/disable NKRO (hardcoded enabled for now due to nature of boot.py)
  • Config file with widget assignments, click/hold timeout, base repeat rate, etc
  • ZIF connectors to attach the MiRage to other Fata Morgana components via ribbon cables
Owner
Zack Freedman
I make projects and then I make YouTube videos about 'em. Sometimes I make streams while making projects. It's honest work.
Zack Freedman
The program converts Swiss notes into American notes

Informatik-Programmieren Einleitung: Das Programm rechnet Schweizer Noten in das Amerikanische Noten um. Der Benutzer kann seine Note eingeben und der

2 Dec 16, 2021
Using Python to parse through email logs received through several backup systems.

outlook-automated-backup-control Backup monitoring on a mailbox: In this mailbox there will be backup logs. The identification will based on the follo

Connor 2 Sep 28, 2022
用于红队成员初步快速攻击的全自动化工具。

关于 Author:m0sway Mail:[email protected] Github:https://www.github.com/m0sway/Jud JuD是

m0sway 46 Jul 21, 2022
A simple API to upload notes or files to KBFS

This API can be used to upload either secure notes or files to a secure KeybaseFS folder.

Dakota Brown 1 Oct 08, 2021
msImpersonate - User account impersonation written in pure Python3

msImpersonate v1.0 msImpersonate is a Python-native user impersonation tool that is capable of impersonating local or network user accounts with valid

Joe Helle 90 Dec 16, 2022
Problem 5: Fermat near-misses

Problem 5: Fermat near-misses fermatnearmiss This is a script that computes fermat nearm misses when the -f option is set and requires users to input

CHRIS BYRON (Int0x80) 1 Jan 08, 2022
frida-based ceserver. iOS analysis is possible with Cheat Engine.

frida-ceserver frida-based ceserver. iOS analysis is possible with Cheat Engine. Original by Dark Byte. Usage Install frida on iOS. python main.py Cyd

KenjiroIchise 89 Jan 08, 2023
Python solution of advent-of-code 2021

Advent of code 2021 Python solutions of Advent of Code 2021 written by Eric Bouteillon Requirements The solutions were developed and tested using Pyth

Eric Bouteillon 3 Oct 25, 2022
TikTok Auto Claimer Made By Aim low!#9999 Leaked By bazooka#0001

Zues Auto Claimer Leaked By bazooka#0001 put proxies in prox.txt put ssid in sid.txt put all users you want to target in user.txt for the login just t

1 Jan 14, 2022
Uproot - A script to bring deeply nested files or directories to the surface

UPROOT Bring deeply nested files or folders to the surface Uproot helps convert

Ted 2 Jan 15, 2022
An html wrapper for python

MessySoup What is it? MessySoup is a python wrapper for html elements. While still a ways away, the main goal is to be able to build a wesbite straigh

4 Jan 05, 2022
A good Tool to comment on xmw

A good Tool to comment on xmw

1 Feb 10, 2022
Graphsignal Logger

Graphsignal Logger Overview Graphsignal is an observability platform for monitoring and troubleshooting production machine learning applications. It h

Graphsignal 143 Dec 05, 2022
Simple calculator with random number button and dark gray theme created with PyQt6

Calculator Application Simple calculator with random number button and dark gray theme created with : PyQt6 Python 3.9.7 you can download the dark gra

Flamingo 2 Mar 07, 2022
Why write code when you can import it directly from GitHub Copilot?

Copilot Importer Why write code when you can import it directly from GitHub Copilot? What is Copilot Importer? The copilot python module will dynamica

Mythic 41 Jan 04, 2023
Module 2's katas from Launch X's python introduction course.

Module2Katas Module 2's katas from Launch X's python introduction course. Virtual environment creation process (on Windows): Create a folder in any de

Javier Méndez 1 Feb 10, 2022
Low-level Python CFFI Bindings for Argon2

Low-level Python CFFI Bindings for Argon2 argon2-cffi-bindings provides low-level CFFI bindings to the Argon2 password hashing algorithm including a v

Hynek Schlawack 4 Dec 15, 2022
Repo to demo translating colab/jupyter notebook to streamlit webapp

Repo to demo translating colab/jupyter notebook to streamlit webapp

Marisa Smith 2 Feb 02, 2022
flake8 plugin which checks that there is no use of sleep in the code.

flake8-sleep flake8 plugin which checks for use of sleep function. installation Using Pypi: pip install flake8-sleep flake8 codes Code Description SLP

1 Nov 26, 2021
Prints values and types during compilation!

Compile-Time Printer Compile-Time Printer prints values and types at compile-time in C++. Teaser test.cpp compile-time-printer

43 Dec 26, 2022