
Designing and building a keyboard - wyager
http://yager.io/keyboard/keyboard.html
======
sdegutis
Related: a hardware hacker that I know recently designed and made a new
keyboard[1], which looks really interesting and fun to make. Fortunately he
also provided really good detailed instructions[1][2] so other people can make
it too. I'm not at the skill stage yet where I can make it myself, but it'll
probably be the first complex hardware project I eventually undertake.

[1]:
[https://github.com/technomancy/atreus](https://github.com/technomancy/atreus)
[2]: [http://technomancy.us/173](http://technomancy.us/173)

------
userbinator
OOP in _keyboard firmware_? Am I the only one who finds this quite a lot more
complex than it needs to be?

> The fact that I2C communication blocks immediately is important. Button
> debouncing is done by counting the number of "frames" for which a key is in
> a certain state.

The obvious solution for this is to synchronise the I2C clock to the matrix
scanning loop, so you receive/send one bit each time through the loop. Even
better, do away with the I2C overhead completely and use a continuous serial
protocol between the two halves.

~~~
wyager
>OOP in keyboard firmware?

I could do it with FP if someone made a Haskell to AVR compiler :)

>Am I the only one who finds this quite a lot more complex than it needs to
be?

What functionality would you propose stripping?

>The obvious solution for this is to synchronise the I2C clock to the matrix
scanning loop, so you receive/send one bit each time through the loop.

That's the _wrong_ solution. The main loop takes some milliseconds.
Communication at that rate would be intolerably slow. And how is that any
better than natively clocked I2C? I'd have to re-implement the entire protocol
_in software_ to get that kind of control.

>do away with the I2C overhead completely and use a continuous serial protocol
between the two halves.

What overhead? Any overhead introduced by I2C is very minimal.

What benefit would a "continuous" (do you mean asynchronous?) serial protocol
have? There are also a number of downsides: 1. It wouldn't work well with the
symmetric halves design. The cable would have to switch the TX and RX lines,
and no common cable does that. 2. It wouldn't support more than two keyboards
at once, unless I implemented a shared-line serial protocol from scratch, and
then why not just use I2C? And using an asynchronous serial protocol doesn't
solve the board synchronization problem.

The new version of the board also breaks out the UART header for people who
want to do exactly this, but the UART is not a better solution.

~~~
userbinator
> What functionality would you propose stripping?

The complexity here is not in the functionality. It's in the design and
implementation.

> The main loop takes some milliseconds.

The MCU has a 16MHz single-cycle core. That means a 62.5ns instruction cycle,
or 16,000 instructions in 1ms. What makes it require >16,000 instructions
every time through the loop?

> What benefit would a "continuous" (do you mean asynchronous?) serial
> protocol have?

I do mean a continuous one, with the master driving the clock at the frequency
of the main loop, and the slave(s) synchronising their transmissions with it.
One of the biggest advantages I see is that you can make use of unused
positions in the key matrix, so that they can be scanned at the same time as
all the others. You just need to know which one, and instead of applying
debouncing/up/down, accumulate the bits of scancode that are sent in and pass
them through.

> 1\. It wouldn't work well with the symmetric halves design. The cable would
> have to switch the TX and RX lines, and no common cable does that.

GPIOs are bidirectional. You can do the crossover configuration entirely in
software, since the current design already detects whether it's plugged in
from USB.

> 2\. It wouldn't support more than two keyboards at once

How would you do this with the current design? They're symmetrical, but I
don't see any way to chain or hub them together (unless you use a USB hub to
connect as many independently as you want...), so I think that's a bit of a
moot point. But if you are thinking of a star topology for this "keyboard area
network"(!), using another unused key position in the matrix of the master for
more extension boards would work. Each board could act as a hub for more, but
this quickly gets into "why would you ever want to do that" territory.

> unless I implemented a shared-line serial protocol from scratch, and then
> why not just use I2C?

Because I2C was defined with different assumptions in mind.

~~~
wyager
>The complexity here is not in the functionality. It's in the design and
implementation.

I'd love to hear some proposals for simplifying the implementation.

>What makes it require >16,000 instructions every time through the loop?

Mostly USB library stuff, I think. Been a while since I profiled it.

>I do mean a continuous one...

Can you further explain this paragraph? I don't know what you mean by "unused
positions in the key matrix".

>You can do the crossover configuration entirely in software

Like I said: I'd have no implement the protocol from scratch, in software. The
hardware UART does not support this functionality.

>How would you do this with the current design?

You can splice a TRRS cable or buy a TRRS splitter. The new version of the
board actually has a dual-jack USB-A connector to make daisy-chaining even
easier.

Again, not sure what you mean by "unused key position in the matrix".

>Because I2C was defined with different assumptions in mind.

Which were?

~~~
userbinator
> I'd love to hear some proposals for simplifying the implementation.

The one thing that stands out is that many of the classes only have one
instance created, and they're classes that don't have much functionality in
them. Returning structures from functions requires a copy, in this case the
array of button states, and copies of them are also created inside of
functions like ButtonDebouncer::update. Only one of these state arrays is ever
needed, so make only one...

The actual matrix-scan loop in HardwareController could also be simplified
greatly; this usually just involves shifting a 1 bit through the row/column
driver output port register(s) and reading the input port(s). There's no need
to turn all the rows/columns off each time, since getting the next col/row is
only a matter of changing which one is being driven. Getting the button number
shouldn't require a multiplication (I'll admit I was pretty shocked when I saw
that!) either, since each iteration of the inner loop is the button after the
previous one, so it can be done with one counter.

> Mostly USB library stuff, I think. Been a while since I profiled it.

I'm more familiar with PS/2 keyboard protocol which is much simpler, but USB
shouldn't be that much more complex to send/receive info once everything has
been initialised (and as I understand from working with USB controllers in
non-keyboard devices, the SIE does much of the actual transfer work in
hardware.)

> Can you further explain this paragraph? I don't know what you mean by
> "unused positions in the key matrix".

There can be row/column combinations which don't have keyswitches at their
intersection, but are scanned anyway. You can connect other units so that they
act like keyswitches when they send information.

> Like I said: I'd have no implement the protocol from scratch, in software.
> The hardware UART does not support this functionality.

Of course.

> Which were?

A non-continuous clock. Transfers that occur in small bursts instead of one
continuous serial stream.

(I have studied the IBM keyboard firmware, and worked with one for an
8051-based controller before.)

~~~
wyager
>The one thing that stands out is that many of the classes only have one
instance created,

To maintain proper levels of abstraction.

>Returning structures from functions requires a copy,

Which is extremely fast, simple, side-effect-free, and likely optimized away
by RVO.

>The actual matrix-scan loop in HardwareController could also be simplified
greatly;

Nothing you described would actually be an optimization. Turning off all the
rows/columns takes 1 cycle.

>Getting the button number shouldn't require a multiplication

Nit-picking. This is fast and easy to read. I'm not going to worry about the
few nanoseconds required for a multiplication.

That's also not an issue of "simplification"; it's just premature
optimization.

>but USB shouldn't be that much more complex

PJRC wrote that library. Not sure what they do.

>There can be row/column combinations which don't have keyswitches at their
intersection, but are scanned anyway. You can connect other units so that they
act like keyswitches when they send information.

Why would I do that? Part of the design is that each individual board is
responsible for translating button presses to USB keycode deltas. This allows
for better distribution of responsibility, and also the boards can be
connected in any configuration/order and maintain the same behavior.

>Transfers that occur in small bursts instead of one continuous serial stream.

What's the downside to this? The bursts occur way faster than human perception
could hope to notice.

Besides, if you want to be pedantic, any serial protocol communicates in
"bursts".

~~~
userbinator
> To maintain proper levels of abstraction.

Abstraction is only a tool, a means to an end; not the end in itself.

> Which is extremely fast, simple, side-effect-free, and likely optimized away
> by RVO.

Copying is one of the fastest things a processor can do, but that's not a
reason to do it unnecessarily, even if the compiler optimiser could simplify
it.

> That's also not an issue of "simplification"; it's just premature
> optimization.

Really? I suppose that if you consider abstraction the ultimate goal, you
might think that shorter, simpler code would be "premature optimization"...

> Part of the design is that each individual board is responsible for
> translating button presses to USB keycode deltas.

That functionality remains the same; the receiving board just collects each
bit of the scancode and passes it through directly to the USB. The sending
board is still the one doing the matrix scan and position-to-keycode
translation. The receiving board is just a passthrough.

> What's the downside to this? The bursts occur way faster than human
> perception could hope to notice.

It adds complexity to the software, because it has to deal with start/stop
conditions, etc.

> Besides, if you want to be pedantic, any serial protocol communicates in
> "bursts".

Not if the clock is continuous; once the receiver and sender are synchronised,
the sender can e.g. keep transmitting 0 bytes when there is nothing to send,
and keycodes (which are all nonzero) otherwise.

------
filereaper
This is interesting.

I've been looking for a split ergonomic type mechanical keyboard, but I
haven't found any. The author just went about building what I was looking for.

~~~
aeontech
How about this one [http://www.kinesis-ergo.com/shop/freestyle2-for-pc-
us/](http://www.kinesis-ergo.com/shop/freestyle2-for-pc-us/) ?

~~~
loup-vaillant
It has one unacceptable flaw: staggered keys. [http://loup-
vaillant.fr/articles/better-keyboards](http://loup-
vaillant.fr/articles/better-keyboards)

------
austinz
This is awesome, and makes me want to try building something similar. On a
related note, can anyone recommend a good source for learning about PCB
design?

~~~
technomancy
GeekHack has lots of resources and knowledgeable folks re: all aspects of
keyboard building:

[http://geekhack.org/index.php?board=117.0](http://geekhack.org/index.php?board=117.0)

I built my board ([http://technomancy.us/173](http://technomancy.us/173))
primarily building on knowledge from geekhack.org and the #geekhack channel on
freenode.

~~~
technomancy
Of course I would add that if your goal is more to make a cool board than
learn about pcbs, it's easier to skip the PCB entirely and just hand-wire the
switch matrix yourself. PCBs make sense at a scale of 5+ but IMO just add
extra overhead for a one-off design.

------
ACow_Adonis
Was just thinking about designing a dream keyboard after the "look at my
chair" and "what's your keyboard" threads here on HN.

Came up with the following requirements:

\- Must be split into a left hand and a right hand.

\- No wires! (since it largely defeats the first point)

\- All the regular relative raised key/ergonomic issues.

\- Mechanical, obviously.

\- Since the point is essentially arbitrarily positioned keyboard hands for
touch typing, there's little purpose in having the letters on the keys:
they're no longer necessarily right in front of you to look at.

\- Optional: can either free-stand successfully or have some various means to
allow it to be mechanically attached to various things/surfaces/mechanisms:
Say if i want to have a lazy-boy chair with each arm being one of the
keyboards.

So get to work HN :P

~~~
Wingman4l7
There's the ErgoDox, a split keyboard which is essentially a DIY kit, but it's
not wireless -- although the potential for setting that up has been discussed.

------
melling
Anyone working on anything a little more non-standard like a modern DataHand?

[http://en.wikipedia.org/wiki/DataHand](http://en.wikipedia.org/wiki/DataHand)

~~~
simias
I had heard of this DataHand before but looking at the wikipedia picture I
realized that the mapping was directly lifted from QWERTY. It seems such a
waste to me to design a new input method and not try to make an optimized
layout for it (since you'll have to relearn to type anyway...)

~~~
clarry
The layout and hardware are things that can be tackled separately and
independently. The hardware isn't a waste if it works.

------
ahultgren
While mechanical switches are everywere, it's simply impossible to find decent
and decently priced scissor-switches. Does anyone know where to find such for
less than $1 each?

~~~
TheCowboy
I have been trying to find these or something similar for my keyboard project,
but I haven't had any luck yet.

I don't know if it's a personal bias after using a Thinkpad keyboard over the
years, but I feel like scissors switches don't put as much stress on my hands
and require less effort.

~~~
userbinator
How about buying a replacement Thinkpad keyboard and getting the switches from
it?

I've used a Thinkpad as well as other laptop's keyboards over the years, and
the Thinkpad ones usually do feel a bit more solid and accurate. They're still
a bit too stiff for me, however, as my regular desktop's keyboard is an
extremely soft rubber dome one (~40g actuation force). I've tried clicky
keyboards, but never really liked them. It's definitely a personal preference.

~~~
TheCowboy
I'd like to do that. The only problem is the switches are mounted on a custom
plate. Fabricating a new plate isn't trivial because of tight tolerances. I
haven't found any examples of someone who has taken on such a project as well.

What keyboard do you use?

------
follower
Here's another take on a custom keyboard:
[http://blog.keyboard.io/](http://blog.keyboard.io/)

------
simias
The website is already half dead, the pictures won't load here. Unfortunately
without the pictures it's a bit harder to follow...

~~~
ivanca
Here it is the whole post as a single pic:
[https://www.dropbox.com/s/hvng9q9rnk6vkfx/keyboard.png?dl=1](https://www.dropbox.com/s/hvng9q9rnk6vkfx/keyboard.png?dl=1)

------
georgeoliver
This is a great article. Funny enough I'm seeing more and more of these
detailed build your own keyboard articles these days. I don't know much about
DIY hardware, has the market recently shifted such that making these things is
much cheaper/easier than a few years ago?

~~~
Rumudiez
Mechanical keyboards have been on the rise again, and that includes hardware
enthusiasts who love to build! I enjoy taking care of my mechanical keyboards
and admire others' collections. The growth here and in other areas like the
RasPi has led to much more smaller production related to these markets and
enabled communities to design their own hardware.

------
theophrastus
I always wanted to see someone make a proper attempt at a keyboard for
"neutral" hand position. hands placed palm down are flexed "pronate", palm up
"supinated", palms facing each other "neutal" is the most relaxed (face it:
we're 'meant' to be holding our hands out ready to strangle each other) so i
want a keyboard not rotated-up slightly, i want one built into a proper cone
(apex up), or two cones (yes yes... i'm sure a couple of breasts might come to
some of your filthy minds)

~~~
leoc
There have been some (shockingly expensive) keyboards in that format. I
thought they were from Kinesis or Maltron, but I can't find them on either
company's website atm. There are also ergonomic steno keyboards which can be
placed in that configuration
[http://geminiwriter.com/ProductdetailsV1.aspx?ID=24](http://geminiwriter.com/ProductdetailsV1.aspx?ID=24)

------
ksrm
Great! I'm now tempted to build something similar but perhaps with Bluetooth
instead.

Does the fact that the keys aren't staggered make it significantly better or
worse to type on?

~~~
wyager
>Does the fact that the keys aren't staggered make it significantly better or
worse to type on?

Depends who you ask! Personally, I think it's a bit more comfortable to type
on than a staggered layout.

Some people _love_ the matrix layout. Some people are rather put off by it.

~~~
technomancy
I haven't used a non-staggered matrix layout, only column-staggered and row-
staggered. Staggering the columns[1] makes allowances for the fact that your
fingers are different lengths, and I like it a lot even though it takes a
while to get used to. I suspect I would like a non-staggered layout better
than row-staggering though.

[1] - like the Ergodox or my own Atreus design does:
[https://secure.flickr.com/photos/technomancy/tags/atreus](https://secure.flickr.com/photos/technomancy/tags/atreus)

~~~
ksrm
Sweet keyboard! It feels like it's missing a whole row of keys though.

~~~
technomancy
Thanks. I intentionally kept the size small since it's not meant to be used as
my primary board; I use an Ergodox when I'm at my desk and only use the Atreus
when I'm out at coffee shops or relaxing on the couch, so the context is
different. Using the fn key for so much definitely takes getting used to
though.

------
wyager
Source here:
[https://github.com/wyager/micromechboard](https://github.com/wyager/micromechboard)

------
rrpadhy
More than a physical keyboard, a keyboard designed for mobile users excites me
more.

Many people use one hand to type on the mobile phone (thumb to be more exact).
However, the design of the keyboard on the mobile screen does not align well
with the natural movement of the thumb. It is painful and hideous.

I believe an Arc keyboard on the mobile screen would be the best design.
Anyone working on something similar?

~~~
leoc
The Twiddler3
[https://plus.google.com/105804767481830727070/posts/j4M9fmRr...](https://plus.google.com/105804767481830727070/posts/j4M9fmRr8dY)
will be a physical keyboard suitable for mobile users. If you want a software
keyboard then ASETNIOP [http://asetniop.com/](http://asetniop.com/) looks
fairly promising, but it's probably only suitable for large tablet-size
screens and hasn't been released yet.

------
taeric
Am I truly that alone in not liking split keyboards? I can certainly use one,
if I have to. I much prefer the standard flat keyboard, though.

Of course, I confess that I have been lucky enough to never have any problems
from one. I fully understand those that need it for medical reasons. I just
don't know as that I would choose it if I didn't need it. (Rather, I know I
would not.)

------
weaksauce
This is awesome... I've wanted my "perfect" keyboard for a long time. Maybe it
might be worth trying to make.

------
chrissnell
Very nice job. Have you thought about an enclosure for it yet? This has always
been the hardest part of PCB designs for me. PCBs are easy and cheap and there
are lots of standard box-type enclosures but you either end up hacking holes
in the sides with a Dremel or forgoing the enclosure entirely.

~~~
jmgrosen
That's one of the greatest use cases for 3D printers! Whether ordering from
Shapeways or printing on your own, making custom cases for projects is pretty
awesome.

~~~
technomancy
Unless you own your own, renting 3D printer time is crazy expensive for
building a case for something this big. Laser-cut acrylic is faster, cheaper,
stronger, and more precise.

------
wolfeidau
Great read, it is very interesting reading about the process you followed
designing and building a hardware project from scratch.

Hopefully this encourages more people to have a shot at building something
interesting, and write about it.

Thanks a lot.

------
malandrew
The keyboard market makes me wonder if there would be a market for custom pcbs
in customs shapes instead of just flat, or possible a 3D printer that can
deposit both a polymer and conductive traces.

~~~
pjc50
Non-flat PCBs would be a massive hassle to solder components to; normal pick-
and-place+reflow is out of the question as the components would fall off, so
you'd have to resort to gluing them on or soldering one leg manually.

Flexible (polyamide) PCBs are already available, with FR4 stiffeners where
components are to be soldered. You could assemble one flat, bend to desired
shape and attach to a form.

------
bananas
Nice work - very tidy and professional-looking. Thanks for sharing.

------
lewaldman
WOW! Last week I was on forums checking out about coverting a rubber dome
keyboard to mechanical...

Now you got me thinking!!! :D

