articles
This is my blog. I write articles here. Click into an article to see its images.
25 May 2022
categories: keebs
tags: dactyl ergodox glove80
Since December 2020 I’ve been using an Ergodox EZ as my main keyboard, both for
work and games. I have my own QMK firmware flashed on it, and I’m nothing but
pleased with it.
![[image] My Ergodox EZ](ergodox.jpg)
Seasons change though, and in January 2021 I found myself backing the Glove80
Kickstarter. I’ve been curious about a curved (“manuform”) keyboard, and this
one looked really slick.
![[image] a Glove80 in Colemak layout](glove80.png)
Up to that point I’d put together keyboard kits with PCBs, and hadn’t yet
3d-printed any enclosures or plates. I kept seeing peoples' cool creations on
reddit though, and eventually I started down that path myself.
Today I’m writing this on my first 3d-printed, handwired keyboard! It’s the
“Dactyl Manuform Open”, available from source code
here.
![[image] my new Dactyl Manuform handwired keyboard](dactyl-manuform.jpg)
For my first attempt I didn’t want to change anything from the stock model, but
I did frankenstein it with some parts from a similar build,
here.
I had noticed in my first print of the Dactyl Manuform that the legs wanted to
adjust themselves a little too much.
I was stymied temporarily by my available tools at the time: I only had an FDM
printer, which didn’t have the right resolution for some of the smaller parts.
My partner recently got an SLA printer though, so I’ve completed the Dactyl
Manuform build.
![[image] the guts of a handwired 3d-printed keyboard](dactyl-guts.jpg)
Handwiring was fun! A little frustrating. My only loose connections were in some
crimps in rectangular cable connectors (my build eschewed the standard 3.5mm
cable between the halves, because one fewer microcontroller is 50% easier to
debug). I ended up cutting out the cable connector and replacing it with
soldered wire connection: it’s not as if I’m going to use either of the halves
by themselves.
I’ve come up with
my own firmware
for it (cribbed from qmk’s). It’s technically Via-compatible, but I don’t know
yet how to set the vendor/product/keymap to make the tool show an accurate
representation of the layout and key mappings. A work in progress, perhaps.
Last night, after typing on it for an afternoon, I started
hacking around in the
source code,
to see if I could get one with the key layout I’ve grown accustomed to with the
Ergodox. I was able to generate something that seems like it’ll fit my needs
better, and then I took another look at one of the Dactyl Manuform’s ancestors:
the Dactyl Keyboard.
![[image] Adereth’s Dactyl Keyboard](dactyl-keyboard.png)
With the exception of the inner row, this matches the key layout of the Ergodox.
I like the 6-key thumb cluster. I’m not sure how comfortable the shape will be,
but aesthetically I think it’s a great board. As I write this, my FDM printer is
making a bottom shell, and my partner’s SLA printer is making a top shell (in
two parts).
![[image] three parts of a keyboard frame: two top shell halves printed in resin, and a bottom shell printed in PLA filament](dactyl1.jpg)
As with my first attempt at Dactyl Manuform, I haven’t tweaked any of the source
code. That may come later, if I really find the shape or lack of an inner column
uncomfortable. Next up: wiring this half, playing with it, and iterating!
![[image] an Adereth Dactyl Keyboard, coming soon to a desk near me](dactyl2.jpg)
23 Sep 2021
categories: keebs lunchtop
I’ve been collecting parts in earnest for two new projects. The basic idea is a
portable, hackable, ruggedized workstation. The first iteration of this idea
came to me from my partner, who is a Homestuck fan. That one is Lunchtop, and
will be built into a red plastic lunchbox from the 70s. The other idea came from
back7.co, and built into a Pelican case.
These projects interest me partly because I like thinking about the ubiquitous
format (“laptop”) being turned on its head and reimagined. And it interests me
partly because I get to build two new mechanical keyboards. This post will focus
on the latter challenge.
Problem
The task is to design and fabricate two keyboards for these computers. The
parameters:
- Lunchtop can fit 8u tall and 11u wide, based on the lunchbox dimensions
- Cyberdeck can fit 13u wide and 7u tall, based on the dimensions of the Pelican
hardcase I’ve selected
- both must have switch plates that fasten to underlying case structure with
screws
- both may have points on the underside of the switch plate for the pcb to
fasten to
- both should only use a single ProMicro-style microcontroller
- both should allow for hotswapping the switches, so I can iterate on the
switchplate design
I was glad to find a hotswap pcb in a good size for the Cyberdeck (5x12). So far
I have not found a good hotswap option for 11u or 10u wide, so I have a few
options:
- I could cobble multiple non-hotswap PCBs together (Gherkin 3x10 and
Yasui 4x10, for instance). This ditches the “single ProMicro” and “hotswap”
design parameters.
- I could cobble multiple non-hotswap PCBs together, and use mill-max
inserts to make them hotswap. This also ditches “single ProMicro”.
- I could cobble multiple non-hotswap PCBs together and cut a bunch of traces,
soldering new wires on to re-grid them. This would allow for “single
ProMicro” but it’s more damaging than I’d like.
- I could follow
this guide for a
3d-printable hotswap “PCB”. This would meet the design parameters but will
take a little more time than options 2 or 3.
Solution
The tipping point came when I started reading this very detailed guide to hand-
wiring one’s
own keyboard. So I’m headed down the road of the printed hotswap “pcb”.
- the hotswap guide requires
npm
and OpenSCAD. I started by making sure
nvm
was installed, and picked the latest
version of npm
. I installed OpenSCAD. I should maybe note that everything I
do on the terminal is in WSL, and everything in a GUI application is in
Windows. And any time I need to build and flash QMK firmware…I do it on a
Mac.
- I made a layout over at
keyboard-layout-editor.com. I downloaded the layout JSON and ran it
through the hotswap guide’s npm script. [note about exact file IO]
- I opened the generated scad files in OpenSCAD. I’m much more familiar with
FreeCAD lately, but I’ve had experience with many CAD programs, so a new one
can’t be all that foreign, right?
26 Aug 2021
categories: keebs steno
tags: ergodox georgi choco pinky3 sofle daisy jd40 tg4x mb44 fruitbar
I’d like to take a moment to rebase where I’m at with steno (and keyboards), and
provide a little context. At the time of publishing this, the blog website has
just gone live, and all prior articles from my steno journal have been imported
and reformatted.
First things first: I have not done much practice with steno in 2021. I have
done quite a bit of practice building mechanical (qwerty) keyboards though. I’ve
also headed off into the weeds with some raspberry-Pi-based projects that I
can’t talk about yet.
A brief inventory of my keyboards:
- I use an Ergodox EZ every day at work. I keep it in qwerty mode, but in the
past I’ve tinkered with
putting steno in its firmware.
- I have a Georgi that’s all souped up with
symbol and media layers,
as well as a
dictionary of nav commands.
- I’ve experimented with split boards smaller than the Ergodox (Kailh Choco,
pinky3, and Sofle). I really wanted something in a smaller profile, and with
rotary encoders. I had a lot of fun building them but in the end the thumb
positions actually started causing my first RSI! I also found that I have
grown used to the huge number of keys available on the Ergodox.
- I’ve made some forays into the land of 40%, with Daisy, JD40 MkII, and TG4X.
This experiment has stalled, as I’m currently waiting on a group buy for the
MB-44.
- I’ve thought long and hard about a 4-row 50% keyboard, and then in my research
found that others are currently making them so I don’t have to. As of this
writing I eagerly await the group buy for the
Fruitbar. I expect that once I
have a more office-centric job I’ll take the Ergodox there, and at home I’ll
use this longboi keyboard.
As far as my steno work goes…it’s been a while since I’ve touched it. I still
would love to get back to it, moreso now even due to my new RSI.
Perhaps I’ll write a proper breakdown of how that machine works for me, and why
I built the firmware and dictionaries the way I did.
25 Jul 2021
categories: Lander Module
tags: HT16K33
Recent efforts have gone into getting the 14-segment alphanumeric display
working. I first tried it with d2r2’s translation of the Adafruit library into
Golang, but that proved a little frustrating.
I then pivoted to periph.io’s experiment, and that worked much better. I do have
to wrap it in some logic for a few reasons:
- out of the box, it panics in certain situations related to the decimal
- I will need a single interface that ends up controlling multiple ht16k33
devices (as in a 6- or 8-digit display)
- I will likely need to implement scrolling text
- I may or may not need the interface to control a whole line of nearby displays
(as in the case where there are two 6-digit timers, but sometimes they work
together to scroll a long string)
But I got the test (ht16k33Test) to work! Here are some next steps I’m tracking:
Software
- incorporate a segmented display into the console, and the modeTest. Have the
display print different things in different modes.
- try using periph/conn/gpio instead of warthog618/gpiod
- begin playing with the i2c multiplexer board
- begin playing with the oled screen
- order a 24-bar graph (also based on ht16k33), and play with that
- begin playing with the analog joystick
- flash the Butterstick with normal-ass keys and write a listener specifically
for those keys
Hardware
- experiment with the textured Prusa print plate?
- Measure the keyboard cutout, 3dp a cover with known rectangle cutouts and
screw-holes.
- Print a switchplate for the butterstick
- Make cuts for other panels, determine how to screw panels on
Comms
- Go to the first build crew meeting
- establish communication with someone who can help with the power circuit
- re-establish who is writing the narrative
As of the last meeting (7/22 with Dr Professor), we had a sketch of the final
layout of touchpoints (see notes/layout_1.png). It did not include the bar-graph
module though…
later that day
First print of a panel was a huge success! I did the thermal printer. I made the
cuts to the vent port, and now the TI-99/4A is ruined! (for any other purpose).
The spacing of the vents is such that I think I’ll need to use #3 screws. It
also happens that that’s the size that should fasten the printer to the plate!
So far I’d been imagining using my stock of #8 screws, but it’ll be good to have
options.
Case in point: I’m printing test plates now for the keyboard backer and keyboard
switchplate, and the first test uses #8 for both, but I can already tell that
#3 might be more fitting to fasten the switchplate to the eventual front plate.
Did some more thinking about the 24-bar graph idea. I think I’ll pick up a few
to play with, but I don’t think there’s room for them on the console.
4 Jul 2021
categories: Lander Module
To dev on the RPi 4 I have to first update it:
sudo apt update
df -h # to check disk has enough free space
sudo apt full-upgrade
sudo apt clean
The game stack (tm) requires some careful thinking. I almost want to thread the
quit signal all the way down, from main to the game server, to the modal game,
to each mode. Because (a) the modalGame Run()
can’t block on the mode’s
Run()
, and (b) we’ll want to wait while a mode finishes Close()
before we
Setup()
the next mode.
So, a Run()
needs to return a signal, and be non-blocking.
And the selector switch needs to provide a signal for its value changes.
And the modalGame’s Run()
needs to listen to three signals:
- quits from above
- changes from selector
- dones from below
Something like this:
func (mg *modalGame) Run(quit chan bool) (chan bool, error) {
done := make(chan bool)
go func() {
run := true
for run{
select {
case <-quit:
mg.Close()
run = false
break
case <-selector.ValueChange():
mg.closeCurrentMode()
// start new mode
case <-mg.currentModeExited:
// clean up
}
}
done<-true
close(done)
}()
}
The overall structure is proofed here: https://play.golang.com/p/EfCbSdv6D3d
Question: do I need games to return a channel for error-forwarding?
Answer: Probably not:
- nobody is going to read the logs of this thing (ooh! that gives me an idea
though: there should be a button in test mode that prints the logs?! Or will
that waste paper?). So it’s reasonable for the game to just log the error and
exit 1 or whatever
- what would the listener do about it? tell the game to quit? the game should
be the one to make that distinction itself
Question: when a mode in the modal game exits organically, what should
happen?
Answer: What this means is that someone has completed the mode. They’ve done
all the sequences, and gotten a report card. However it happens, the console
should be rendered inoperable until the User Switch is reset.
In program terms, I think it’s ok for the current modalTest to exit out.
main
gameServer.PlayUntil(signalCaught)
modalGame.Run(...)
listen to changes to the mode selector switch
testingGame.Run(...)
launchGame.Run(...)
landingGame.Run(...)
In the actual program, the testing, launch and landing games will not end of
their own accord, but keep listening for a rising edge of the user switch. This
behavior allows the user to “reset” their experience, if necessary. (Though
perhaps they’d have to hit a kill switch to get the sequence to stop in the
first place).
main
gameServer.PlayUntil(signalCaught)
modalGame.Run(...)
listen to changes to the mode selector switch
testingGame.Run(...)
launchGame.Run(...)
listen to changes to the user switch
launchSequence.Run(...)
landingGame.Run(...)
listen to changes to the user switch
landingSequence.Run(...)
Question: do we even need the games' Run() to return an exit code? I wonder
what kind of runtime (pun intended) error would be catastrophic in that way.
Answer: let’s wait and see, after I do the next level of tests
End of day progress report:
Work continues apace! The modeTest runs, but it has at least one bug :P
-
I should have an “off mode” handy.
-
I should try out stubGame.
-
if I leave testingGame, the listener for the selector stops? All I got was
go run src/cmd/modeTest/main.go
game server starting
selector value changed to 1
selector value changed to 2
…and that’s it! no more input made any changes. I had to kill the main
process and one subprocess to get the gpio back.
First step: more logging.
Well, second step. First step: try to sleep.
3 Jul 2021
categories: Lander Module
A few things are clear today:
- I should dev on the RPi 4, so I can remote SSH in with VS Code
- The next software hurdle to cross is the modal architecture. To that end I’ve
worked up an interface and implementation that uses a guitar pickup switch as
a SP5T instead of its normal operation (three digital outs, five positions:
100, 110, 010, 011, 001)
- This modal idea is about to get a little hairier. I’m coalescing ideas about
different sets of components, that get read at different times. The program
essentially has to go through a state machine. Perhaps I should build the
state machine as a first-class entity.
The first step is probably to graph it out.
- During development of this machine, I should keep a close eye on how reliable
the experience is. Are there intermittent errors with pin lines unable to open
or close? etc. If it becomes unreliable, I need to start keeping a reliable
version printed and ready to install in the chassis. I don’t mean to use this
policy to encourage breaking things, but rather to mitigate against what I
know has been my pattern with software as a whole…
Oh gosh, I just realized a SP4T won’t work to do both power and data, unless I
do some fancy diodes and voltage step-downs. No, let’s keep it simple and use
two admin keyswitches.
For the admin touchpoints, I wonder if I can fit them all (2 keyswitches and a
USB…and an HDMI?) in the expansion slot. Or if I should just make them regular
slide switches behind a screwed-on panel. Hmmmm, no, that’s too much touching,
and what if the panel loses threads and falls off?
For that HDMI question, I wonder if RPi can connect to phone hotspot and I can
ssh in through that? New ticket!
So, next step is to mock this up using the guitar pickup switch as the “mode”,
and assume power switch is on. Then, set up at least two different mode games,
that each use the same toggle and LEDs, but with different behavior (e.g. test
mode flashes an led while the toggle is held, but the landing mode latches the
led).
30 Jun 2021
categories: Lander Module
I have successfully transcribed my simple python script to a
slightly-less-simple go program. No, I don’t know why I call python files
“scripts” and go files “programs”.
I’ve been using the https://github.com/warthog618/gpiod library. It seems to do
what we need. I didn’t immediately understand the WithFallingEdge option, but
edge detection is easy enough to implement, and I bet if I tried again to figure
it out I could.
It’s time to try the next hurdle, and this time to start in Go. I have a Quad
Alphanumeric display backpack here, and it’s supposed to work over I2C. So let’s
get it soldered and breadboarded!
29 Jun 2021
categories: Lander Module
First tests are promising!
I have completed a 3d-printed bracket mount for the digital joystick.
I have also completed a short program that reads a single mom-off-mom toggle
and latches an LED every time it goes up or down. It is written in Python, but
my hopes are high that I can transcribe it to Go next. Some resources I should
look into for that effort:
- https://medium.com/@farissyariati/go-raspberry-pi-hello-world-tutorial-7e830d08b3ae
- https://github.com/warthog618/gpiod
- https://github.com/stianeikeland/go-rpio
I have also ordered the 3rd round of parts from Adafruit and Digikey, and
finished intake processing for the 2nd round. Upcoming experiments are:
- write to a 14-segment timer/countdown display (using mission-start time, and
also event-start time)
- write to an OLED display, perhaps by putting a ship graphic overlaid on a
landing zone graphic.
- super extra credit: use an OLED display like an attitude gauge!
- write a “main alarm” sequence, with buzzer
When the 3rd batch of stuff comes in, I’ll be able to
- play with I2C I/Os
- vet some more toggle switches
I should not purchase any bulk switches or buttons until after the second
production meeting with Deeps, on 8 Jul.
oof, getting this first script done feels good. Hurdle over!
More thoughts, this time about upcoming 3d-prints:
- should print a couple more joystick brackets
- should print several more switch guards
- should test hole size for m2 and m3 screws (for mounting PCBs on)
27 Jun 2021
categories: Lander Module
I’ve been getting up to speed on LED driving and button/switch driving, so that
I can prototype a Raspberry Pi with code that reads a switch, and turns on and
off an LED. A couple of thoughts here:
The RPi 0W has 26 available GPIO pins. This feels like a lot, but if I pair one
or two LEDs with each toggle switch, I’ll run out quickly.
Next I found this AW9523 breakout,
which controls 16 I/O over I2C. So, if I give up 2 ports on the main board
itself for I2C, and I can chain 4 of these expanders together, that gives me a
total of 88 I/O ports!
The printer code I’ve been working with so far in Tissubots takes the serial
pins away too (Tx/Rx are GPIO 14 and 15), so we’re looking at about 86 pins.
what about our 14-segment digit displays? those run on i2c as well! first, know
that they can be chained up to 8 in a row, so I only need one bus to drive all
the segment displays on the whole console.
Can I run a second i2c bus on the pi?
[This](https://www.instructables.com/Raspberry-PI-Multiple-I2c-Devices/
instructable seems to think I can run 5 additional busses beyond the builtin one, if I modify the /boot/config.txt
.
So, where does that leave us? Out of the 26 available GPIO pins, maybe:
2 for tx/rx to printer
2 for I2C: 4 I/O expanders (64 pins)
2 for add'l I2C: all segmented displays (up to 8 4-digit backpacks)
2 for add'l I2C: 4 I/O expanders (64 pins)
2 for add'l I2C: 4 I/O expanders (64 pins)
2 for add'l I2C: 4 I/O expanders (64 pins)
2 for add'l I2C: 4 I/O expanders (64 pins)
12 remaining pins on RPi
=
64 * 5 + 12 = 332! :flushed:
ok so it’s time to order some of those expanders I guess.
I won’t use all those pins, obviously. In fact, I will probably set up one chain
for just LEDs (using its nifty constant-current feature), and one chain just for
buttons/switches/joysticks (using pull-up or -down resistors). I still have 3
(supposed) available I2C buses! maybe if I use a buzzer that requires its own
breakout? or I could add in a little OLED display (4-wire SPI).
A “pull-down” resistor goes between digital pin and ground. Then put the button
between voltage and the digital pin. The resistor pulls the pin down unless the
button is pressed (connecting voltage).
A “pull-up” resistor is like “pull-down”, but swap the ground and supply nodes.
All else being equal, it seems to me it would save power if we use pull-down.
How to select the resistance: resistor should be “1/10 less than the input
impedance of the digital pin” (does this mean 90% of the input impedance?)
(or 10kOhm if you can’t be bothered).
RPi has onboard pull-up and pull-down resistors, but if we put all the buttons
and switches on expanders we’ll need to use resistors in connection to the
expander.
It would be especially cool if each panel on the console ended in its expander.
That way it would be very quick to swap out a dud panel. Just need a board near
the RPi that has all the JSTs for the different expanders. Maybe…huh, maybe
even a Hat for it! Can I make my own RPi hat?
18 Jun 2021
categories: Lander Module
I printed out the “space shuttle toggle switch guard”.
In plating I selected the single guard then did “Add Part” to expand it to a row
of 5. Then, in print settings I made sure to go into Expert > Infill and set
“Solid infill threshold area” to 16mm^2. This ensures there’s a solid infill for
the upright portions of the guard, extending just below the joint with the side
plates.
Overall, quality was pretty low, probably due to all the jumping around, and
bridging.
For the next attempt, I may want to re-model the holes for the switches, since
the switches I bought are nowhere near fitting the holes as-is.
I might also want to try a build in a different orientation? or with different
infill options (was it really necessary to use solid, or to use infill at all?)
Anyway, good first attempt!
Oh, for the second iteration I could avoid the 12-hour time by just printing
squares with holes in, and inset the squares to the guard I have! CA glue will
be a key part of the build anyway.
In other news, first Digi-Key order arrived and it is great! Lots of buttons to
push and the joysticks live up to their name (especially the ball-top one).
For the next round of orders I want to try to get a large square button or two,
for a “main alarm” function. These can be pricey, but with only 1 on the board I
think it’s worth it.
I also want to try out some “standard round” toggle switches, because I can
print out the cover to make it look more spacey.
17 Jun 2021
categories: Lander Module
A couple weeks ago Dr Professor asked me if I want to build a thing for Caravan
Rally (happening this October). So far we’ve been talking about a “lander
module” experience. Here are some parameters:
- it should be fun, engaging and diverting
- it should involve 2-3 people working together
- it should last about 5 minutes
- it should entail the operators landing a spacecraft
- it should be able to answer the question “how well did the operators land the
spacecraft?”
Immediately my mind jumped to Moon Lander, and to the Apollo 11 VR experience.
Drawing from those, and from this awesome Kerbal controllerf1, I’m building a
game/toy/gadget that fits the above parameters.
I’m tracking parts and tickets in an Airtable.
Project is due in mid-September.
I will have regular meetings with Dr Professor to provide progress reports.
CONSOLE
The main piece of this is a console that can fit in someone’s lap, have a bunch
of knobs and switches and gauges on it, and be an operable computer for landing
a spaceship.
The LM is meant to be operated by one person in a Caravan vehicle.
HARDWARE
I’ve purchased a TI-99/4A to provide the “chassis” for this console.
I am experimenting with various buttons and switches that light up. I intend to
build these into panels which can be screwed to the chassis, and plugged into a
pcb. The pcb will connect the panels to power, and to a central controller like
a Raspberry Pi or Arduino.
If I design any PCBs, their cad files will be stored in [a private] repository.
The whole thing will be powered by battery that may potentially be charged by
USB and/or cigarette lighter.
Here are some ideas for devices that the console could use:
- sliders, buttons, and switches. Momentary vs toggle.
- a joystick, e.g. for precise control of maneuvering thrusters
- dial or linear gauges. Not sure yet how to achieve this except perhaps a
decal’d voltage meter. Perhaps a stepper motor and small screw.
- 7-segment LCD indicators, e.g. for a mission timer
- OLED or e-ink screen, e.g. for precise graphics
- thermal receipt printer, e.g. for printing event summary, and/or scenario
parameters
- extra-special credit: real-looking attitude indicators
- speakers, for playing sound effects of explosions etc.
- buzzers, for when an alarm goes off.
More flighty ideas include:
- the computer networks to a “GM” computer that allows a second human to control
the sequence parameters
- the computer networks to a small switch computer in each other car, to
indicate caravan readiness
- the computer has an audio output (cable, bluetooth, fm transmitter) for making
the ship sounds be more…immersive
- an on-board accelerometer and/or microphone, to implement an interaction like
“if this gauge goes dead, try tapping on it”
SOFTWARE
The sequence code is another key part of this deliverable. It should fulfill the
primary parameters, and if possible fulfill these secondary parameters:
- the sequence should develop iteratively, so that I can always deliver a
serviceable experience.
- the layers of the application should stay separate, so that I may reuse them
in future projects (that may or may not involve spaceships).
All source code will be stored in [a private] repository.
MANUAL
Another piece of this is a section of the Flight Manual dedicated to operation
of the Lander Module (LM). This document will be read and interpreted by others
in the Caravan vehicle.
The whole Flight Manual document will include more elements than I provide from
this project.
SEQUENCE
Here’s where the fun starts. In order to keep it simple and deliver an MVP, I
feel I should focus on core competencies:
- Main sequence. Player must push buttons in correct order to transition
through multiple stages of landing.
- Controls include momentary and toggle inputs
- Indicators include a mission timer (counting up), event timer (counting
down), and various LEDs
- Stages are: Atmospheric Entry, Main Drag (Parachute), Maneuvering, Touchdown
For each stage, the controls and indicators do slightly different things. For
instance:
- During Atmo the controls change the ship’s attitude, and the indicators show
attitude, heat levels, and altitude. Final action to change stage is to eject
the heat shield in a specific heat/altitude window.
- During Main Drag, the controls are really just to deploy parachutes, and the
indications are altitude, vertical speed, and ground speed. Stage exit is to
cut the parachutes in a specific altitude/speed window.
- During Maneuvering, controls are to align the ship with the landing zone, and
make sure you don’t crash. Indicators are speeds, and some kind of
“pointed-in-the-right-direction”-ness. Stage-exit action is to deploy landing
gear when you’re in position and have 0 ground speed.
- During touchdown, controls are to burn the landing thruster. Indicators are
speeds, and whether or not you went to space today.
That’s probably as simple as I’m willing to make it. If and when that’s done, I
can implement new layers to it. For instance:
- Parametric stages: These variables affect how the controls operate, but
probably shouldn’t make the experience harder, just different. After all,
the operators of this will likely get one “real” shot with it, so we can’t
expect them to try many times, growing and learning.
- Maybe the landing zone has really low/high gravity.
- Maybe it has a heavy/light atmosphere.
- The fuel or RCS mass starts at different levels?
- Alarms: when the alarm goes off, it will blink various LEDs around the
console. Based on which LEDs they are, there’s a different resolution pattern
to perform (as detailed clearly in the Appendix of the LM Flight Manual).
- the Heat Shield won’t separate, gotta blow the backup clamps
- chutes won’t open, gotta deploy the backups
- landing gear won’t deploy, cut throttle and blow airbags
- Glitches:
- maybe a DRO wonks out and starts showing garbage.
- Maybe the whole console goes dead until you “power cycle” it.
- New Sequences:
- There’s an opportunity for a single “Launch” sequence at the beginning
of the Rally. Maybe we could use this console for that too.
- Maybe there’s a Training sequence for people to play with in the car before
they have to do the real thing.
- Maybe there’s a choice of landing zone.
- More complex stages:
- the Drag stage splits into two, for fast chutes and slow chutes
- More complex inputs and outputs:
- the Touchdown stage gets a screen and a joystick, and a “Moon Lander”-esque
feel.
Questions for Design Team:
- should we implement a Training Mode that lets them practice landing, say, on
the Moon?
- will we encourage teams to write their own margin notes in the Flight Manual?!
25 Nov 2020
categories: steno
tags: qmk plover
I just realized: using alt to mouse-select multiple cursors in VS
Code does not trigger the OSL to fall back. Is that a task I do with the
dictionary instead? No, dictionary can’t help there. HMM!
Perhaps a key on the symbol layer that does a TO(BASE)
. yup, that works!
I’ve also printed out some cheat-sheets, and now I guess nothing is
stopping me from developing some muscle memory…
I’ve started a tiny bit of coding with steno. It’s alive!
Starting to think about building my own “single stroke commands” dictionary,
but because it’s so many different chords, thinking of building a generator
that takes an input of all the chords for each modifier (plus a few others
for nav/cursor control), and then it prints out all the hundreds of
permutations! Some things I’m learning about dictionary entries as I do
this:
-
a /
is present to delineate strokes
-
a -
is present to delineate left-hand vs right-hand, but only
- if there are no left-hand keys in the chord
- if writing it down without a
-
would show ambiguity (HRPB
is
either HR-PB
“license”, or H-RPB
“hit-and-run”)
- if there is no ambiguity? (e.g.
*ET/K-L
“ethical”)
- only if there’s also no
*
.
Does Learn Plover! have anything to say on this subject?
When defining dictionary definitions by hand, you should be sure to
include the hyphen when appropriate
I think I can handle that. Why not always generate a -
until I see it
break?
One final note, someone’s blog recommended keeping the dictionary handy,
that being able to quickly add or edit definitions was really helpful. I
wonder if I could set up a single key in my layer or a brief in a
dictionary to run that Plover function?
24 Nov 2020
categories: steno
tags: ergodox georgi
Made a cheat-sheet for the single-stroke commands dictionary
tonight. Did my first cut, paste and undo! The shapes are a little goofy
but I think they’ll suffice for my needs. Might even allow me to free up
some keys on the firmware layer (no need for arrows, letters, or functions).
I did order an Ergodox. The clutter argument was very compelling. It’ll
take 4 weeks to get here, so in the meantime I’ll keep practicing on Georgi.
I’m excited to put together a firmware for Ergodox that does everything I
need–and with LED control!
23 Nov 2020
categories: keebs steno
tags: qmk butterstick georgi gergo ergodox
A few things I noticed in practice tonight
-
tapping the OSL key doesn’t let me alt-tab with impunity, but holding it
does.
-
my custom nav layer doesn’t support select-all, cut, copy, paste, undo,
or redo. I wonder again if I should record the number of times I use
a feature in a day, and put those at the front and center.
oh, also ctrl-backspace (or alt-bsp and cmd-bsp on mac).
Even if I put my most common commands on the first nav layer, I still
need either
- (hw, current status) a qwerty keyboard standing by.
pro: I have it (it’s free)
con: slow to switch from typing to commanding
con: BIG desk clutter
con: need the qwerty keyboard for typing while learning steno
- (hw) a macropad (e.g. Butterstick) standing by.
pro: I have it (it’s free)
con: slow to switch from typing to commanding
con: smol desk clutter
con: need the qwerty keyboard for typing while learning steno
- (fw) three or more layers on the georgi.
pro: I have it (it’s free)
pro: everything is at my fingertips (it’s quick to switch)
pro: no clutter!
con: patience and time to tweak and learn the layers
con: need the qwerty keyboard for typing while learning steno
- (hw) A BIGGER georgi, with more keys to hand (see: Gergo. I
think maybe Gergoplex isn’t enough columns).
pro: it’s a kit I can build myself (another round of custom
switches, this time maybe kailh silver?)
pro: everything is at my fingertips (quick to switch)
pro: no clutter!
pro: less need to layer the commands (quicker than switching)
pro: do not need a qwerty kicking around while I learn steno
con: hard to program it to be steno sometimes and command
sometimes?
con: I’d need to build my own enclosure for it.
- (hw) white tiger option: get an ergodox already (~$350).
pro: it’s a kit I can configure myself (it does hotswap)
pro: everything is at my fingertips
pro: no clutter!
pro: less need to layer the commands
pro: do not need a qwerty kicking around while I learn steno
con: hard to program it to be steno sometimes and command
sometimes?
con: expensive
- (sw) learn and develop the Single Stroke commands dictionary in
Plover.
pro: I have it (it’s free)
pro: VERY easy to reconfigure a broken brief on the fly
con: need the qwerty keyboard for typing while learning steno
con: patience and time to tweak and learn the briefs
Options 4 and 5 (Gergo and Ergodox) are similar enough that I can
runoff them: With Gergo, I have to design and build the enclosure,
and buy keycaps and switches. With Ergodox, I just have to spend
~$280 marginally (and maybe make or buy steno-friendly keycaps).
With Gergo, I get to make it look however I want, with Ergodox, no
such personalization.
GERGO ERGODOX
+ personalized - cost
- kit work - not personalized
Actually, now that I think about it, the Gergo wouldn’t be a full size
qwerty, so I’d be training (1) steno, (2) columnar qwerty, and (3) gergo
commands and shortcuts for qwerty. Ergodox loses on customization, but
“costs” less in terms of money-work, and wins on me not doing that (3)
training.
I’d also point out that the “do not need the qwerty keyboard for typing
while learning steno” is not worth nothing.
In the end it’s really down to an ideological choice: do I want to do this
retraining of my brain and fingers through software, firmware, or
hardware? And even if I do it through software, do I want the greater
hardware anyway to speed things along, declutter the process, and/or be
more ergonomic for me? (For the record I have yet to experience any RSI…)
I will sleep on it.
22 Nov 2020
categories: steno
tags: qmk butterstick georgi
Last night / this morning I read a lot about how QMK works with
layers. Then I worked up keymaps for both the Butterstick and the Georgi!
The first milestone is complete: I can successfully alt-tab any number of
times!
Next milestones:
-
make the nav layer key (and fn layer key) momentary-layers (like OSL, but
that didn’t seem to work immediately).
OSL(layer)
- momentarily activates layer
until the next key is pressed.
See One Shot Keys for details and additional functionality.
// One-shot layer - 256 layer max
#define OSL(layer) (QK_ONE_SHOT_LAYER | ((layer)&0xFF))
Defined in quantum/quantum_keycodes.h
and used in the action_for_keycode
function of quantum/keymap_common.c
.
#ifndef NO_ACTION_ONESHOT
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:;
// OSL(action_layer) - One-shot action_layer
action_layer = keycode & 0xFF;
action.code = ACTION_LAYER_ONESHOT(action_layer);
break;
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:;
// OSM(mod) - One-shot mod
mod = mod_config(keycode & 0xFF);
action.code = ACTION_MODS_ONESHOT(mod);
break;
#endif
which leads to
#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT)
...
#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key))
...
num action_kind_id { ACT_LAYER_TAP = 0b1010 /* Layer 0-15 */ }
#define ACTION(kind, param) ((kind) << 12 | (param))
Of course all this code is just a bunch of bit shifting!
Let’s try OSL()
one more time, just in case…
Yeah, it’s probably because I had #define NO_ACTION_ONESHOT
in my
config.h
, huh?
Nope, OSL
still isn’t working on the georgi. Switching to Butterstick
to see if it’s a steno mode thing.
Yes, OSL
works on the butterstick. Also, implementing
oneshot_layer_changed_user
in keymap.c
makes it print to the QMK
toolbox (I wasn’t seeing those prints from Georgi).
Switching back to Georgi for one more shot, then I’ll compromise with
TG
and hope I don’t get in a bad layer state.
I got it! I had to delete the #define NO_ACTION_ONESHOT
, and go
into rules.mk
(beware there’s one for the keyboard and one for the
keymap!) and set NO_TAPPING = no
! Now I can use OSL
to shift layers.
-
maybe write a custom function like TH(kc1, kc2)
, where if you tap it
sends kc1
, and if you hold it sends kc2
. For inspiration:
LT(layer, kc)
- momentarily activates layer
when held, and sends
kc
when tapped. Only supports layers 0-15.
// L-ayer, T-ap - 256 keycode max, 16 layer max
#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF))
...
// M-od, T-ap - 256 keycode max
#define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF))
Since stubbing this out and then playing with my layers quite a bit
above, I realized I had an extra blank key next to the media keys, so
I no longer need to double up TH(KC_VOLD, KC_MUTE)
, but maybe it’d be
a fun experiment sometime anyway. Another day. Today my nav and media
layers work great and I should take some time to practice them (and
to practice steno lol).
20 Nov 2020
categories: steno
tags: plover wsl qmk
I adopted a nav/command dictionary that I found on the internet.
I have by now also read the section in Learn Plover! about dictionaries, so
I feel well-equipped to start tabbing my way around.
The only real trouble is (on a Windows machine) I keep
this repo checked-out to a directory in WSL2,
which is not (easily) accessible from Windows, where I’ve installed Plover.
Whoops.
Ok, I realized (again) that this will not solve all my nav use cases. I
still need a way to alt-tab that either lets me hold alt while hitting tab
any number of times (and sending those inputs individually, so I can see
results), or I need a brief for “hit alt-tab twice in a row” etc, up to
like 4 or 5 (the max number of windows I’d want to be open in a space
anyway). Gonna try setting some of my own nav briefs for this.
<experiments with Alt_L(Tab Tab Tab) ensue>
I think this particular behavior is not something I can achieve with steno.
Perhaps it is time to back up and take another look at the QMK symbol layer
bound to my bottom left pinky key. Another night.
19 Nov 2020
categories: steno
tags: plover georgi qmk
Today I updated my qmk_firmware repo [now deleted] to match what Jane has on
their side. I tried a PR, but that got really mucky with a changed file and a
changed submodule, so I backed out, saved patches of my commits, and completely
remade my fork. It turns out the changed file also hit my new fork (wtf?), but
the patches applied just fine.
Last night I read about dictionaries, and how Learn Plover! teaches the
shift/ctrl/alt/super keys. It’s interesting, and I’m ready to start
tinkering with my own dictionary for nav & control. I also tried using the
Georgi’s pre-baked Symbol layer, but had some trouble with the alt-tab
behavior I expect [see previous post].
It’s worth re-flashing with the updated qmk from germ/qmk_firmware, and if that
doesn’t work I can still try my own symbol map and if THAT doesn’t work perhaps
I can fall back to using a steno dictionary entries to define “alt-tab once”,
“alt-tab twice” etc.
17 Nov 2020
categories: steno
Maybe I’ll be satisfied looking at the progress.json activity page
to see how consistently I’m practicing. It’s no heatcalendar, but it’ll do.
In other news, I’ve got a cheat sheet of punctuation and whitespacing (the
book didn’t mention, but it’s T*AB
for a tab character). Next item todo
is to figure out how people manage modifier keys and navigation keys.
The real crux is this use case: hold down ctrl (or cmd). Press tab any
number of times. Also hold shift. Press tab some more times. Let go of
shift… let go of ctrl (cmd).
15 Nov 2020
categories: steno
tags: plover
Upgraded to Plover v4.0.0. When they say “back up your plover.cfg”
that file is in C:\Users\<username>\AppData\Local\plover\plover\
.
Wondering if there’s a way to stay accountable for daily activity without
bloating this journal file.
14 Nov 2020
categories: steno
tags: plover
journaling with steno now! ok back to qwerty. that took a few
minutes, but I’m having fun learning about the control mechanisms (to
insert a space or not, to capitalize or not), as well as punctuation and
positioning chords. I’d like to try to find a testimonial about Plover’s
“space placement” option (before or after chord output). I feel like that
option may (a) have a medium-to-large impact on the workflow for coding vs
prose, and (b) be really hard to retrain later.
13 Nov 2020
categories: steno
tags: georgi
Got a little practice in. I realized I’m not yet ready to fully
drop the progress-tracking. My reasoning is that I’m doing this from at
least 2 different computers still, and Typey Type doesn’t have user
accounts, so if I want to track progress there I should copy the file down
after every session.
Thankfully I was able to quickly build a
CLI tool that will help me
merge two JSON files into one, summing the values along the way. That should
help in the task of saving the progress JSON at least.
I also remembered that because Georgi only has the two rows for my fingers
instead of a steno machine’s standard 3, the third thumb button (on both
sides) is my number bar modifier.
I wonder again how I might use the extra two pinky keys on the left side
too, since I probably won’t need–wait…i’m not so terrible at georgi qwerty! [that last phrase only took several minutes to puzzle out, and
even then i didn’t know all the punctuation keys]. Anyway, even while I’m
doing steno I’ll want a way to hit arbitrary shortcuts. That’ll be
interesting.
12 Nov 2020
categories: steno
Started the spilliams/steno repository! I
hope in the end it’ll contain useful tidbits I picked up along the journey, as
well as any custom dictionaries I develop.
Some historical background on the journey so far is below. Going forward,
I don’t want this journal to be just a list of wpm counts and times (though
I’ll certainly include some for milestone tracking). The last few times I
dusted off the steno machine I ended up putting a lot of effort into time-
and wpm-tracking, so much that it became Not Very Fun Any More.
Less of that from now on, focussing on the fun parts instead!
20 Feb 2020
categories: steno
tags: georgi
[historical]
1 day of practice in February. 13wpm on Georgi.
16 Dec 2019
categories: steno
tags: georgi
[historical]
1 day of practice in December. Still hovering around 10 wpm on Georgi (using
Typey Type). I started punctuation though!
25 Nov 2019
categories: steno
[historical]
4 days of practice in October. 1 in November.
6 Oct 2019
categories: steno
tags: soft/hruf georgi
[historical]
That stint in August lasted 5 days. Seeing a pattern…
It’s ok though. I’m having fun with this when I have fun. Any practical
effects will be a nice bonus, but not worth beating myself up about if I
don’t achieve.
In August I got up to about 16 wpm on Typey Type with the SOFT/HRUF.
Now I’m using the Georgi, around 13 wpm on Typey Type.
25 Aug 2019
categories: steno
tags: soft/hruf
[historical]
That stint in May lasted 4 days. Back at it now. 10 wpm on Typey
Type with the SOFT/HRUF.
12 May 2019
categories: steno
tags: SOFT/HRUF
[historical]
I took baseline typing speed tests at www.typingtest.com with my
2015 macbook air and WASD v2 keyboards: 73 and 76 wpm, respectively.
I also started learning the SOFT/HRUF machine, with an initial count of 8 wpm on
Typey Type.