** THIS PROJECT HAS BEEN SUPERSEDED BY ML67. Generic Minila stuff is on the master branch. Things specific to my ML62 are on the ml62 branch. **
This project grew out of the goal to make the perfect keyboard for myself. I already had the Filco Minila which I liked a lot. It has a bunch of switches at the bottom to rearrange some of the keys about. I had it configured to resemble a Sun Type 3 or Happy Hacker keyboard as much as it would allow. However there were some things that I thought could be improved so I decided to hack.
I wanted to fix the function layer. Both Filco and Happy Hacker have completely disregarded the old Unix shortcuts when they positioned the keys on the Fn layer. There is a long tradition of Ctrl-A being Home and Ctrl-E being End. Also Ctrl-D for PgDn and Ctrl-U for PgUp. To me, it seams so obvious and ridiculous to make up entirely new combinations. I wanted to fix all the quirks and make a real, proper hacker keyboard for Unix-like systems.
I've got a portable thin-client setup. My mainframe is an Amazon EC2 instance. My screen is a Nexus 7 (2013) and my keyboard is running T.M.K. firmware on a Teensy 2.0. Yep that's Lego.
I use JuiceSSH to connect to the EC2 instance via Mosh then run my stuff inside a tmux session. I try and stay in the console as much as I can, however I do find myself jumping to a browser, sometimes a lot.
It took a little bit of experimentation to work out the keymap that works best for me. I have now settled on this layout. It works well with OS X, Android and a Linux terminal. I have not attempted to use it under Windows or any Linux desktop environment or window manager.
- Set Shift-Esc to send a ~.
- Add Fn2-Media keys.
- Swap | and ` keys so they are no longer back-to-front.
- Move Capslock to Fn2-Shift.
- Move Meta next to Space, and right under my left thumb.
- Move Fn1 next to Meta.
- Move Super out of the way because I use a foot pedal for it.
- Set Ctrl-H to another Backspace key. Ctrl-H does not always act as a backspace normally, though I would like it to.
- Set Ctrl-A to another Home key. Like Ctrl-H, Ctrl-A does not always go to the start of the line. This would drive a Windows user crazy, but as I do not use Windows I'm not concerned.
- Remove unused keys to make the arrow keys easier to find by feel.
- Fn1-hjkl are now the alternative arrow keys.
- Set Fn1-udae to page up, page down, home and end like Emacs.
- Create a Tmux key which sends the Tmux prefix with one press.
- Meta-Backspace deletes a word.
-
Hardware
1.1 Filco Minila
1.2 Teensy 2.0
1.3 Nexus 7 -
Hacking
2.1 Switch To Circuit Board Relationship
2.2 Original Row/Column Matrix
2.3 Compressing The Matrix
2.4 Patching The Circuit Board
-
Firmware
3.1 Setup
3.2 Rows And Columns
3.3 Keymap
3.4 LEDs
3.5 Writing To Your Teensy -
Chassis
4.1 Buying The Lego
4.2 Building
 4.2.1 Frame
 4.2.2 Mounting The Keyboard
 4.2.3 The USB Plug
 4.2.4 The LEDs
 4.2.5 Teensy Button Hole
-
Software
5.1 JuiceSSH
5.2 Amazon EC2
5.3 Mosh
5.4 Tmux
I choose the Minila originally because I wanted a small mechanical keyboard. I didn't have any mechanical keyboard at that time and I loved that it could be configured like the Happy Hacker. I decided against the Happy Hacker because it's too expensive to not use. I've heard the Topre switches are similar to the Cherry Browns which I don't like.
My hardware is marked as revision Matrix Ver1.0 2012/10/17
. If your hardware
says anything else, there's no knowing what is different. Maybe nothing, maybe
everything. Either way, with this guide you should be able to hack it anyway.
Dimensions...
I originally got a Teensy 3.0. It didn't work because it's a different architecture. I also tried an Arduino Leopold which I had laying around. It didn't work either. Some of the pins worked, but not enough of them. I then ordered what I should have got in the first place. Everything went smooth with the Teensy 2.0.
This was an experiment I tried out because I had the tablet laying around and thought I should see how it went as a display. I wasn't very impressed initially, but after persevering for a little while, I sorted out most of my problems.
I'm using an OTG cable to connect the keyboard to the tablet's USB port.
I'm getting internet via Wifi or tethering from my phone.
These instructions are for hacking a Filco Minila. The revision that I am
using is Matrix Ver1.0 2012/10/17
. These instructions may be compatible with
other revisions, however I cannot promise anything as I don't have the hardware
to check. It should become apparent quite early if your revision is different.
If you notice no differences in the switch to circuit board
relationship, then you should be okay.
For now I'm going to refer to the keys, not by the label that is written on them, but by the position within the keymap that they will be placed. Initially we don't need to worry ourselves about what they key will do. All that matters is to recognise that the key exists.
First up, we need to work out how each switch is connected to the original matrix. If you don't have a strong grasp of how a keyboard works I recommend you read Keyboard Matrix Help.
Key | K00 | K01 | K02 | K03 | K04 | K05 | K06 | K07 | K08 | K09 | K0A | K0B | K0C | K0D | K0E |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Col | C1 | C1 | C2 | C3 | C4 | C4 | C5 | C5 | C6 | C7 | C8 | C8 | C6 | C1 | C10 |
Row | R3 | R7 | R7 | R7 | R7 | R6 | R6 | R7 | R7 | R7 | R7 | R6 | R6 | R6 | R1 |
Key | K10 | K11 | K12 | K13 | K14 | K15 | K16 | K17 | K18 | K19 | K1A | K1B | K1C | K1D | Kxx |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Col | C1 | C1 | C2 | C3 | C4 | C4 | C5 | C5 | C6 | C7 | C8 | C8 | C6 | C10 | |
Row | R1 | R0 | R0 | R0 | R0 | R1 | R1 | R0 | R0 | R0 | R0 | R1 | R1 | R2 |
Key | K20 | K21 | K22 | K23 | K24 | K25 | K26 | K27 | K28 | K29 | K2A | K2B | K2C | Kxx | Kxx |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Col | C2 | C1 | C2 | C3 | C4 | C4 | C5 | C5 | C6 | C7 | C8 | C8 | C10 | ||
Row | R1 | R2 | R2 | R2 | R2 | R3 | R3 | R2 | R2 | R2 | R2 | R3 | R4 |
Key | K30 | K31 | K32 | K33 | K34 | K35 | K36 | K37 | K38 | K39 | K3A | K3B | Kxx | Kxx | Kxx |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Col | C15 | C1 | C2 | C3 | C4 | C4 | C5 | C5 | C6 | C7 | C8 | C14 | |||
Row | R1 | R4 | R4 | R4 | R4 | R5 | R5 | R4 | R4 | R4 | R5 | R3 |
Key | K40 | K41 | K42 | K43 | K44 | K45 | Kxx | Kxx | Kxx | Kxx | Kxx | Kxx | K4C | K4D | K4E |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Col | C0 | C13 | C9 | C9 | C11 | C9 | C14 | C11 | C12 | ||||||
Row | R6 | R1 | R3 | R2 | R3 | R0 | R5 | R5 | R5 |
Using the data we collected in the previous step, we can now construct a table to help us visualise the matrix.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | K11 | K12 | K13 | K14 | K17 | K18 | K19 | K1A | K45 | |||||||
1 | K10 | K20 | K15 | K16 | K1C | K1B | K0E | K41 | K30 | |||||||
2 | K21 | K22 | K23 | K24 | K27 | K28 | K29 | K2A | K43 | K1D | ||||||
3 | K00 | K25 | K26 | K2B | K42 | K44 | K3B | |||||||||
4 | K31 | K32 | K33 | K34 | K37 | K38 | K39 | K2C | ||||||||
5 | K35 | K36 | K3A | K4D | K4E | K4C | ||||||||||
6 | K40 | K0D | K05 | K06 | K0C | K0B | ||||||||||
7 | K01 | K02 | K03 | K04 | K07 | K08 | K09 | K0A |
As you can see, the matrix has 8 rows and 16 columns.
The first thing you need to understand is that for each row, column and LED requires one pin on your controller; in our case, the Teensy. The purpose of compressing the matrix is to join columns together so that you don't require so many pins on your controller. Compressing is completely optional, however as I'm using a Teensy 2.0 with only 25 pins, I will have no room to expand once I've added a single LED.
To determine which columns can be merged is quite simple. If you can place a column on top of another without any keys sharing a position, then they can be merged.
For example:
-
Column 15 can be merged with Column 0, 3, 7, 9, 11, 12 or 14.
-
Column 4 and 5 are completely full so they cannot be merged with anything.
Matrix after compressing:
| COL1 | 1 | 0 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | COL2 | 12 | 2 | 13 | | | | 15 | | | |
COL3 | 11 | 14 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
0 | K11 | K12 | K13 | K14 | K17 | K18 | K19 | K1A | K45 | |
1 | K10 | K20 | K41 | K15 | K16 | K1C | K30 | K1B | K0E | |
2 | K21 | K22 | K23 | K24 | K27 | K28 | K29 | K2A | K43 | K1D |
3 | K00 | K44 | K3B | K25 | K26 | K2B | K42 | |||
4 | K31 | K32 | K33 | K34 | K37 | K38 | K39 | K2C | ||
5 | K4E | K4D | K4C | K35 | K36 | K3A | ||||
6 | K0D | K40 | K05 | K06 | K0C | K0B | ||||
7 | K01 | K02 | K03 | K04 | K07 | K08 | K09 | K0A |
From now on I'll reference the columns like so:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | K11 | K12 | K13 | K14 | K17 | K18 | K19 | K1A | K45 | |
1 | K10 | K20 | K41 | K15 | K16 | K1C | K30 | K1B | K0E | |
2 | K21 | K22 | K23 | K24 | K27 | K28 | K29 | K2A | K43 | K1D |
3 | K00 | K44 | K3B | K25 | K26 | K2B | K42 | |||
4 | K31 | K32 | K33 | K34 | K37 | K38 | K39 | K2C | ||
5 | K4E | K4D | K4C | K35 | K36 | K3A | ||||
6 | K0D | K40 | K05 | K06 | K0C | K0B | ||||
7 | K01 | K02 | K03 | K04 | K07 | K08 | K09 | K0A |
There are two ways you can go about patching the board:
- Get a plug that will attach to the original circuit board.
- Connect straight to points on the board.
I was going to go the first way, but the plug I bought did not fit so I decided to just go ahead without it. If you do decide to connect to the board, you need a 28 pin male connector with 2mm spacing. Be aware that the Teensy has 2.54mm spaced pins so the two will be a bit of a pain to connect.
The pinout of the original header:
28/27 | 26/25 | 24/23 | 22/21 | 20/19 | 18/17 | 16/15 | 14/13 | 12/11 | 10/09 | 08/07 | 06/05 | 04/03 | 02/01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
GND | C12 | C11 | C10 | C9 | C8 | C7 | C6 | C5 | C4 | C3 | C2 | C1 | C0 |
OC13 | LED1 | LED2 | +5v | C15 | C14 | R7 | R6 | R5 | R4 | R3 | R2 | R1 | R0 |
- Find a point on the board labeled R0.
- Connect your multimeter to the R0 pin of the original header.
- Running between the switches are the diodes. You cannot see them, but their pins are exposed. Check the diodes surrounding the switch for a connection back to the header. Once you have found one, that can be used as a point to take your connection.
For each of the switches there is a diode. You need to make sure that you take your connection from the other side of it. I found testing with a multimeter to be a bit difficult but managed by using the following process:
- Find a switch.
- Find the next component that the switch is connected to. Do this by checking the surrounding unlabeled points for zero resistance.
- Finding the other leg of that component should be quite obvious. Just look for another point at right angles to the first point that has zero resistance back to one of the pins of the original header.
- Your connection point can be the pin of the original header, or any point on the board that is connected to that header, including the leg of the component you just found.
!!!!!To help, here is the pin-out of the original header.
28/27 | 26/25 | 24/23 | 22/21 | 20/19 | 18/17 | 16/15 | 14/13 | 12/11 | 10/09 | 08/07 | 06/05 | 04/03 | 02/01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
GND | C12 | C11 | C10 | C9 | C8 | C7 | C6 | C5 | C4 | C3 | C2 | C1 | C0 |
OC13 | LED1 | LED2 | +5v | C15 | C14 | R7 | R6 | R5 | R4 | R3 | R2 | R1 | R0 |
Once that's all done, all that's left is soldering up some leads to each of your connection points.
!!!I've connected my board to some connectors which will plug straight into my breadboard. The connectors got like this.
Pin | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
Row | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Pin | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
Col | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
By now you should know which keys you want to remove. You should do so now before your board gets delicate from dangling wires.
IMPORTANT: If you decide to remove keys, and you have compressed your matrix, you may have to start again if you change your mind and want to add a key back in.
Now it's time to get out the soldering iron and physically connect those rows up. So start by finding a C1 and a C12 on the circuit board and short them out. Then connect C0, C2 and C11 together. Then continue for the rest.
!!!Find any point on the board and with the label.
To program the Teensy, you must first press the reset button. Once you've built a case around your keyboard, it may be difficult to reach. If you wish, you can place another button somewhere else where it's easier to reach.
!!! explain how...
!!! In spite the pins on each of the keys being name Cn and Rn, that does not mean that they are the rows and columns. In fact, it's actually the other way around. I needed to reverse this behaviour due to incorrect polarity coming from the Teensy which prevented the signal to pass the diode on the Minila circuit board.
Getting the source:
git clone ... <path>
cd <path>
git submodule add ... keyboards/ml62
cd keyboards/ml62
See matrix.c.
See keymap_plain.c. See keymap_common.h.
Configuring the LEDs
First you need to compile your source.
# Setting the path is a hack and pretty specific to my own setup. I'm only putting it here so I don't forget.
PATH=/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin:${PATH}
cd keyboards/ml62
make clean
make
Then open up the teensy
app and flash ml62_lufa.hex
to your teensy.
I didn't know initially what size or shape I wanted. I had a quick look at what dimensions a Lego brick is, and I worked out pretty quick that Lego is ideal for quick mock ups. The dimensions of Lego seems to fit a lot of electronics perfectly and it's easy to work the plastic with not much more than a few jewellers files.
I was concerned that maybe it would fall apart, but so far that hasn't been a problem. A few pieces come off from time to time and I'll find them in the bottom of my bag. Sometimes cracks will appear but it's been much stronger than I expected.
If you are still concerned, I have read that you can permanently bond blocks together using acetone, although I have not tried it myself.
I first used Bricksmith to attempt to build my chassis. I would not recommend it. The program is nice, but it was a waste of time to do much more than get an idea of how much Lego I needed to buy.
- I was over-engineering because I was underestimating the strength of the bricks.
- It was so slow to change your mind and try something new.
- Anything with angles was difficult.
- Its hard to hack your bricks with a file or drill.
- Without the actual components you are trying to fit into Lego, modelled and imported into your CAD program, it was ultimately just guess work anyway.
So do what you have to do to decide what to buy, then head over to bricklink and buy double or more. For the amount of Lego you need for a keyboard it isn't expensive to buy too much.
I found Lego much easier to work with than Bricksmith and around 70 Euro for 3 to 4 times as much as I needed.
The keyboard backplate is exactly 36 bricks wide
- Boot up an EC2 instance.
- Configure an Elastic IP
- Point a DNS record to your Elastic IP
- Open up ports ... to allow yourself SSH access.
JuiceSSH is an awesome SSH client for Android. It's lacking in a few features I'd really like to see, but they are steadily progressing so I'm confident that it'll just be a matter of time before I'm completely satisfied.
- Configure to SSH into the DNS record your created.
I highly recommend using Mosh instead of SSH, especially if you are using a Tmux key. I'm not sure the exact reason, but multiple Tmux key-presses do not register correctly with regular SSH.
- Install Mosh on your EC2 instance.
- Open up ports...
- Configure JuiceSSH.
Notes:
- Mosh does not yet forward SSH keys. Any SSH keys you require on your EC2
instances will need to be installed in
~/.ssh
.
Tmux stands for 'Terminal Multiplexer'. If you are familiar with screen
, then
it's a modern version of that. If not, then it's a way to display multiple
terminals simultaneously. It give you keyboard control over their position and
size. You can split your display or have a series of tabs or a combination of
both. You can background your session and continue on another machine and you
can share your terminal with multiple users.
tmux is sweet as heck is a good overview of the differences between Tmux and Screen.
- Install it via your system package manager. It should be available.
tmux
will create a new session andtmux a
will attach you to an existing session.
That should be enough to get you started.
The config I'm using is on
github. You will
need to save it to ~/.tmux.conf
Now you have a Linux terminal. You'll need to get command-line tools to do what you want to do. There is plenty written on the web about this, I won't repeat it. My work-flow revolves around these tools:
- Vim
- Tig and Git
- the-silver-searcher
I'm not finished yet, but it's becoming clear that I'll probably never finish. I'm using my new keyboard every day and am satisfied with it, there may be some minor changes along the way, but layout seems perfect.
Ultimately I'd like to build a replacement laptop. It doesn't matter if I'm still using EC2 for most of my computing power. I think a local Linux installation with Fluxbox would make a better window manager than Android though. I'm imagining something like this:
For the short term, I'd like to be able to charge the Nexus while I've got a keyboard connected. I should also mount the screen a little bit more sturdy. A rubber mat on the base would be nice to stop it from sliding around. I may also look into getting some nice new key-caps with the actual keys printed on them.