# Quantum Hand-Wiring Guide Parts list: * *x* keyswitches (MX, Matias, Gateron, etc) * *x* diodes * Keyboard plate (metal, plastic, cardboard, etc) * Wire (strained for wiring to the Teensy, anything for the rows/columns) * Soldering iron set at 600ºF or 315ºC (if temperature-controlled) * Rosin-cored solder (leaded or lead-free) * Adequate ventilation/a fan * Tweezers (optional) * Wire cutters/snippers ## How the Matrix Works (Why We Need Diodes) The microcontroller (in this case, the Teensy 2.0) will be setup up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example: Column 0 being scanned Column 1 being scanned x x col0 col1 col0 col1 | | | | row0 ---(key0)---(key1) row0 ---(key0)---(key1) | | | | row1 ---(key2)---(key3) row1 ---(key2)---(key3) The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column. When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected: Column 0 being scanned Column 1 being scanned x x col0 col1 col0 col1 | | | | x row0 ---(-+-0)---(key1) row0 ---(-+-0)---(key1) | | | | row1 ---(key2)---(key3) row1 ---(key2)---(key3) We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is col0: 0b01 col1: 0b00 │└row0 └row1 A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious: Column 0 being scanned Column 1 being scanned x x col0 col1 col0 col1 | | | | x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1) | | | | x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3) Remember that this ^ is still connected to row1 The data we get from that is: col0: 0b11 col1: 0b11 │└row0 └row1 Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this; Column 0 being scanned Column 1 being scanned x x col0 col1 col0 col1 │ │ | │ (key0) (key1) (key0) (key1) ! │ ! │ ! | ! │ row0 ─────┴────────┘ │ row0 ─────┴────────┘ │ │ │ | │ (key2) (key3) (key2) (key3) ! ! ! ! row1 ─────┴────────┘ row1 ─────┴────────┘ In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|` Now when we press the three keys, invoking what would be a ghosting scenario: Column 0 being scanned Column 1 being scanned x x col0 col1 col0 col1 │ │ │ │ (┌─┤0) (┌─┤1) (┌─┤0) (┌─┤1) ! │ ! │ ! │ ! │ x row0 ─────┴────────┘ │ x row0 ─────┴────────┘ │ │ │ │ │ (key2) (┌─┘3) (key2) (┌─┘3) ! !
# 
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk

ROOTPART=$(strip $(subst ",, $(CONFIG_X86_GRUB_ROOTPART)))
#")) # fix vim's broken syntax highlighting


ifeq ($(CONFIG_X86_GRUB_IMAGES),y)
  define Build/Compile
	$(MAKE) -C grub compile
  endef

  define Build/Clean
	$(MAKE) -C grub clean
  endef

  define Image/cmdline/jffs2-64k
    block2mtd.block2mtd=$(ROOTPART),65536 root=/dev/mtdblock0 rootfstype=jffs2
  endef

  define Image/cmdline/jffs2-128k
    block2mtd.block2mtd=$(ROOTPART),131072 root=/dev/mtdblock0 rootfstype=jffs2
  endef

  define Image/cmdline/ext2
    root=$(ROOTPART) rootfstype=ext2 $(CONFIG_X86_GRUB_BOOTOPTS)
  endef

  define Image/Build/grub
	mkdir -p $(KDIR)/root.grub/boot/grub
	$(CP) \
		$(STAGING_DIR)/usr/lib/grub/i386-pc/stage1 \
		$(STAGING_DIR)/usr/lib/grub/i386-pc/stage2 \
		$(STAGING_DIR)/usr/lib/grub/i386-pc/e2fs_stage1_5 \
		$(KDIR)/root.grub/boot/grub/
	$(CP) $(LINUX_DIR)/arch/i386/boot/bzImage $(KDIR)/root.grub/boot/vmlinuz
	sed \
		-e 's#@CMDLINE@#$(strip $(call Image/cmdline/$(1)))#g' \
		-e 's#@BAUDRATE@#$(CONFIG_X86_GRUB_BAUDRATE)#g' \
		./grub/menu.lst > $(KDIR)/root.grub/boot/grub/menu.lst
	PATH="$(STAGING_DIR)/usr/sbin:$(STAGING_DIR)/bin:$(PATH)" ./gen_image.sh $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).image $(CONFIG_X86_GRUB_KERNELPART) $(KDIR)/root.grub $(CONFIG_TARGET_ROOTFS_FSPART) $(KDIR)/root.$(1)
  endef
endif

define Image/Build
	$(call Image/Build/grub,$(1))
	cp $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).fs
	cp $(LINUX_DIR)/arch/i386/boot/bzImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz
endef

$(eval $(call BuildImage))

$(eval $(call RequireCommand,fdisk, \
	Please install fdisk \
))
EYMAP( \ k00, k01, k02, \ k10, k11, \ ) \ { \ { k00, k01, k02 }, \ { k10, KC_NO, k11 }, \ } ``` Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring. Let's say that instead, we wired our keyboard like this (a fair thing to do): ``` ┌───┬───┬───┐ │ ┋ │ ┋│ ┋ │ ├─┋─┴─┬┋┴───┤ │ ┋ │┋ │ └─────┴─────┘ ``` This would require our `KEYMAP` definition to look like this: ``` #define KEYMAP( \ k00, k01, k02, \ k10, k11, \ ) \ { \ { k00, k01, k02 }, \ { k10, k11, KC_NO }, \ } ``` Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `KEYMAP` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it. ### `keymaps//default.c` This is the actual keymap for your keyboard, and the main place you'll make changes as you perfect your layout. `default.c` is the file that gets pull by default when typing `make`, but you can make other files as well, and specify them by typing `make handwired/:`, which will pull `keymaps//keymap.c`. The basis of a keymap is its layers - by default, layer 0 is active. You can activate other layers, the highest of which will be referenced first. Let's start with our base layer. Using our previous example, let's say we want to create the following layout: ``` ┌───┬───┬───┐ │ A │ 1 │ H │ ├───┴─┬─┴───┤ │ TAB │ SPC │ └─────┴─────┘ ``` This can be accomplished by using the following `keymaps` definition: ``` const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( /* Base */ KC_A, KC_1, KC_H, \ KC_TAB, KC_SPC \ ), }; ``` Note that the layout of the keycodes is similar to the physical layout of our keyboard - this make it much easier to see what's going on. A lot of the keycodes should be fairly obvious, but for a full list of them, check out [Keycodes](keycodes.md) - there are also a lot of aliases to condense your keymap file. It's also important to use the `KEYMAP` function we defined earlier - this is what allows the firmware to associate our intended readable keymap with the actual wiring. ## Compiling Your Firmware After you've written out your entire keymap, you're ready to get the firmware compiled and onto your Teensy. Before compiling, you'll need to get your [development environment set-up](getting_started_build_tools.md) - you can skip the dfu-programmer instructions, but you'll need to download and install the [Teensy Loader](https://www.pjrc.com/teensy/loader.html) to get the firmware on your Teensy. Once everything is installed, running `make` in the terminal should get you some output, and eventually a `.hex` file in that folder. If you're having trouble with this step, see the end of the guide for the trouble-shooting section. Once you have your `.hex` file, open up the Teensy loader application, and click the file icon. From here, navigate to your `QMK/keyboards//` folder, and select the `.hex` file. Plug in your keyboard and press the button on the Teensy - you should see the LED on the device turn off once you do. The Teensy Loader app will change a little, and the buttons should be clickable - click the download button (down arrow), and then the reset button (right arrow), and your keyboard should be ready to go! ## Testing Your Firmware Carefully flip your keyboard over, open up a new text document, and try typing - you should get the characters that you put into your keymap. Test each key, and note the ones that aren't working. Here's a quick trouble-shooting guide for non-working keys: 0. Flip the keyboard back over and short the keyswitch's contacts with a piece wire - this will eliminate the possibility of the keyswitch being bad and needing to be replaced. 1. Check the solder points on the keyswitch - these need to be plump and whole. If you touch it with a moderate amount of force and it comes apart, it's not strong enough. 2. Check the solder joints on the diode - if the diode is loose, part of your row may register, while the other may not. 3. Check the solder joints on the columns - if your column wiring is loose, part or all of the column may not work. 4. Check the solder joints on both sides of the wires going to/from the Teensy - the wires need to be fully soldered and connect to both sides. 5. Check the .h file for errors and incorrectly placed `KC_NO`s - if you're unsure where they should be, instead duplicate a k*xy* variable. 6. Check to make sure you actually compiled the firmware and flashed the Teensy correctly. Unless you got error messages in the terminal, or a pop-up during flashing, you probably did everything correctly. If you've done all of these things, keep in mind that sometimes you might have had multiple things affecting the keyswitch, so it doesn't hurt to test the keyswitch by shorting it out at the end. # Securing the Teensy, Finishing Your Hardware, Getting Fancier Firmware Now that you have a working board, it's time to get things in their permanent positions. I've often used liberal amounts of hot glue to secure and insulate things, so if that's your style, start spreading that stuff like butter. Otherwise, double-sided tape is always an elegant solution, and electrical tape is a distant second. Due to the nature of these builds, a lot of this part is up to you and how you planned (or didn't plan) things out. There are a lot of possibilities inside the firmware - explore [docs.qmk.fm](http://docs.qmk.fm) for a full feature list, and dive into the different project (Planck, Clueboard, Ergodox EZ, etc) to see how people use all of them. You can always stop by [the OLKB subreddit for help!](http://reddit.com/r/olkb)