Now that I’m 6,400 miles away from my dear robot track saw and its precision positioning system, I need to find a new outlet for my embedded Rust habit.
Luckily, I’m now that much closer to Shenzhen, so I thought I’d build myself a travel ergonomic keyboard — in particular, a low profile, ortholinear (keys are in straight columns, not staggered), split (two entirely separate halves) wireless keyboard.
I’ve wanted one for years; back in 2017 I tore down the closest commercial offering I could find, which is what led me to the whole wild custom keyboard scene.
There’s prior art in that DIY community, of course. Technomancy has been working on the Atreus since 2014 and now reached the summit of indie popularity that is a successful Kickstarter (nice job Technomancy!). The Mitosis is the most impressively designed-for-hobbyist-manufacture open hardware anything I’ve seen — it and its derivatives (Centromere, get it?) are probably the most similar physical designs to what I have in mind.
Of course, as per Reddit Keyboard Law, such devices can never be sold retail, only via group buys that ended a week before you’ve discovered them.
But that’s okay — by now you should know that I won’t spend 2 hours and $100 on a purchase if I could have instead spend an unbounded amount of time and money on multiple design iterations and deeps dives into technical esoterica.
Luckily for me, when the virus shit hit the fan I had an nrf52840 USB dongle development board in my backpack, which means I was able to spend my 14 day Taiwan arrival quarantine on this project.
Of course, rather than just modifying the manufacturer provided Makefiles and C examples (one of which was literally a bluetooth keyboard), I decided to instead to do it in Rust.
About 30 hours later, I can now print “hello world” over USB serial and via bluetooth. I also learned much more than I wanted to know about linking, memory layout, and how to use a disassembler in anger (which looks exactly like “hacking” in Hollywood movies — namely staring at a screen full of hexadecimal garbage and muttering under one’s breath).
One reason it was so difficult to use this chip from Rust is that that the bluetooth radio (accessed via manufacturer’s SDK) is controlled by a “softdevice” (proprietary binary blob), so there is a lot of fancy linker stuff required to setup memory in just the right way so the softdevice had its own little bit of RAM and the hardware could jump between softdevice and user application code.
Here were some highlights:
Some SDK function would declare a FooInterrupt
using “weak linking”, and it’d be silently dropped on the floor since the Rust linker script declared the name as FooHandler
instead; so when the interrupt fired the hardware would jump to an infinite loop default handler.
A bug in llvm-objdump causes it to silently drop sections when converting ELF to HEX.
This was particularly pathological because I was testing my understanding by decompiling the ELF output, which showed that the section existed and had the correct data.
My pal Jake and I only discovered the issue by writing horrible C code to println
arbitrary memory regions as integers at runtime.
Discovering that previously-paired bluetooth devices were stored non-volatile memory, which meant that incorrect behavior would persist even after reflashing my program and and power-cycling the hardware. (I only discovered this because I had a second dongle I could test with to ensure I wasn’t actually losing my mind.)
Discovering that the llvm linker (unlike the GCC linker used by the manufacturer in its examples) will not link against C files if the file doesn’t contain any functions that’re called. That seems reasonable, but the manufacturer SDK uses an “observer” pattern implemented as C preprocessor macros that place function pointers into specially named program segments that’re iterated over. This difference in linker behavior between GCC and LLVM manifested as an error only if USB and bluetooth ran at the same time (both worked fine separately…)
After getting through all that, I’m now pretty sure I can start working on my actual keyboard. Here are the next two big projects:
Wireless communication: How should a computer and two half-keyboards all talk with each other? The Mitosis design uses a separate receiver plugged into the computer that both halves talk to, but that’s extra hardware to design/manufacture and precludes using the keyboard with a phone/tablet.
Alternatively, each half could talk separately to the computer via bluetooth, but then you’d have to pair twice (ugh!) and keyboard layers wouldn’t work properly (i.e., pressing the shift key on the left half wouldn’t make the right half uppercase).
So my current plan is to have the keyboard halves talk with each other and only one of them pair with the computer via bluetooth — TBD whether the halves will also chat with each other over bluetooth, or if I can find a lower-power (but secure!) protocol.
Industrial design: I don’t yet have access to a CNC machine or laser cutter, so for the first iterations I’ll take on the aesthetic challenge of making a bare PCB attractive. Luckily, PCBs can be ordered in several colors and exposed pads are literally gold plated; it’s hard to make a gold plated thing ugly, right?
Also: How many keys should each half have? I’m thinking 4 rows and 5 columns with 3 thumb buttons, but definitely let me know if you have experience / religious fervor about little keyboards and alternate layers.
I’ll finish the PCB design early this week, so if the local supply chain spirits take kindly to this foreigner and I can find a reflow oven (or hotplate / toaster to sacrifice), I’ll have a prototype in time for next month’s newsletter.
Like many people, when I was in college I “experimented” with foolish and dangerous activities like running Linux on the desktop.
I’ve mellowed as I’ve aged, but still fondly remember the thrill of the XMonad tiling window manager on multiple monitors — in particular, its responsiveness. With a few fast keyboard shortcuts, I could throw windows between monitors, arrange windows side-by-side, and immediately move focus to exactly the window I had in mind.
XMonad also supports “virtual desktops”, which I used to organize windows by task. For example, when working on a web app I’d put a terminal window, Emacs window, two web browsers (one for my app, the other for looking up documentation) all on the same virtual desktop. Then, when I wanted to do something else, I could switch to an empty virtual desktop, effectively saving my previous one “away for later”.
This workflow really helped me focus, but it’s near impossible on Mac:
Mac virtual desktops are broken in several ways, most notably long unskippable animations that send your keypresses to the previously focused application; see the comprehensive Grumpy.website writeup.
(The “reduce motion” accessibility setting turns the sickness-inducing animation into a mere fade in/out, but unfortunately is still unskippable; as a consolation prize, though, you can turn off the “new window” animation via defaults write -g NSAutomaticWindowAnimationsEnabled -bool false
.)
Mac is obsessed with applications rather than windows, so even if I try to organize windows by task across virtual desktops, when I “Command-Tab” to try and move from, e.g., Emacs to a browser window on one desktop, there’s a chance Mac will instead focus me to a different browser window on a different virtual desktop.
I can’t comment on the situation on Windows (which I haven’t used since the Windows 2000 glory days), but this wonderful/depressing piece on The Decline of Usability suggests that things aren’t much better there either.
Perhaps the most damning evidence that built-in window managers are woefully inadequate is that all the applications where people spend a lot of time — web browsers, mail clients, programming IDEs, drawing programs, terminals, etc. — have developed their own systems of tabs, buffers, split panes, etc.
Conceptually all of these programs are (trying to) solve the same window manager problems — having multiple things “open” at once, showing them side-by-side, and switching focus between them — but they each do it with a different set of hotkeys.
My frustration with this situation led me to develop Finda, which I’ve enjoyed immensely over the past few years. Finda is just one program in a whole cottage industry of apps like the Alfred productivity suite, Amethyst tiling window manager, Hammerspoon toolkit, TotalSpaces, and CommandTab+ that all enhance/tweak/repair Mac’s glitz-over-usability desktop.
But I’m dubious about the ability of third party programs to combine into a cohesive experience, especially given that we’re all at the mercy of ever-shifting platform behavior. (e.g., Finda is somewhat busted on Catalina, since Mac made some internal change where its window API now returns duplicate entries and overlays that aren’t user-facing but are programmatically indistinguishable from real application windows.)
However it might be implemented (as tweaks on Mac/Windows or a full desktop GUI running on Linux or a hypervisor), it’s worth thinking about what characteristics a professional desktop computing environment might have — one that embraces responsiveness, consistency, and doesn’t need to sell itself in a crowded shopping mall.
A few observations on this topic:
While everyone has been obsessed with mobile over the past decade, desktop screen real estate has become wildly cheap (4k TVs are $300!). There are probably many useful interactions to be explored here. E.g., when searching a PDF, why settle for a seeing a list of matches, each with just a few surrounding words for context? Why not open every matching page in its own window and use the already-familiar window navigation/control commands to discard unwanted matches?
90% of my computing work involves the same few activities: Writing/responding to email, editing text/code in Emacs, navigating the file system, running terminal commands, and looking at PDFs and websites. So a handful of exemplar tasks may suffice for evaluating design ideas. For example “save this newsletter as a PDF and email it to a friend” would take me 30 seconds on Mac, even though it only takes 5 seconds to articulate the thought; could a new desktop make this task possible in under 10 seconds?
Video calls and screen sharing will only become more popular, and the desktop layer (rather than individual apps) is probably the best place to manage sharing both input and output. E.g., “Share just this virtual desktop and allow my collaborator to control the mouse there” or “allow my collaborator to type text, but only in these two application windows” (Aside: Has anyone actually successfully shared more than one window but less than all of them?)
Similarly, taking and annotating screenshots and quick videos is a wonderful way to communicate ideas, but it’s high-friction today — the best solution in many cases is to aim your smartphone at your monitor or record yourself drawing on paper. (Again, see Grumpy.website on Mac’s inexplicable self-sabotage.)
If the market is professionals — say, people who make $80k+ annually from looking at a computer all day — and they’d be open to reinvest 5% in tooling that improves their efficiency/comfort, then the system could be designed as a holistic software/hardware package including monitors, drawing pads, cameras, eye tracking, weird keyboards, dials, etc.
I’m also curious about the status quo: Why don’t we see more divergence between the work environments of casual and professional computer users? They’re all in the same cafes on the same laptops.
Or is all of the divergence in software? Professional analysts spend 90% of their time in Excel, architects in AutoCAD, programmers in Emacs, venture capitalists in Superhuman, etc. and everyone reverts to casual clicking around the 10% of their time when they need to share a file or look at a web page?
In that case, perhaps the marginal benefit of improving “secondary tasks” just isn’t there — the “productivity tool” obsessives who are recomiling their Linux tiling window managers and clipboard extension APIs are just enjoying the digital equivelent of carefully arranging staplers and pencils on a physical desk.
What do you think?
Oil-filled, magnetic transmission, bellow system, hydraulic shock absorber; adjectives I don’t normally associate with a wristwatch.
Americans have until April 30 to buy “the best investment in the world”, a 20-year government savings bond yielding 3.5%. (The current 20-year treasury rate is under 1%.)
For my fellow curious input device and CAD friends: a Space Mouse teardown.
“The government released 300,000 tons of pork from the strategic pork reserves.”
Early talk about developing an iPad thinking notebook app, Muse.
Two years of prototyping a VR desktop window manager, some wonderful attention to detail in making flat windows in 3D.
“Multiphase Turbulent Gas Cloud from a Human Sneeze” (scroll to first figure).
“A kinematic coupling aims to join two separable parts precisely and repeatable to one another.”
“The United States has a large trade deficit, significant current account deficit, major fiscal deficit, and a deeply negative international investment position.” I don’t think much about international finance, but found this overview of the global dollar short squeeze captivating.
R/C toilet paper roll is the hero we deserve
“The lack of a good framework to understand China’s initial quarantine is probably a better explanation for Western inaction than stuff like "people don’t understand exponential growth.”
“Can we compile C code into powerpoint?” Yes, but should we?