I've changed the backend of my blog. You shouldn't notice any differences, except that comments are disabled for the time being.
All links to the site should continue to work.
If you notice any problems, even small ones, please send me an email.
I've changed the backend of my blog. You shouldn't notice any differences, except that comments are disabled for the time being.
All links to the site should continue to work.
If you notice any problems, even small ones, please send me an email.
Lately I’ve been messing about in Godot, a framework for making video games (similar to Unity).
I wanted to make a 3D game. In my game, you live in a geodesic dome, and can’t go outside, because mumble mumble mumble poisonous atmosphere?.
A geodesic dome, I learned, is related to the icosahedron, or d20 from RPGs.
A simple dome is the top half of the icosahedron. As they get more complex, you divide each triangle into more and more smaller triangles.
So to make a nice geodesic dome, we could find one (I failed), make one in Blender (too hard), or use some math to generate one in Godot. And to do that math, we need to know the list of 20 icosahedron faces. Which basically just needs the list of the 12 vertices!
Now, obviously you could look up the vertices, but I thought of a more fun way. Let’s put 12 points on a sphere, make them all repel each other (think magnetically, I guess), and see where on the sphere they slide to. Maybe they will all be spaced out evenly in the right places. Well, here’s what it looks like:
So… kinda? It was certainly entertaining.
By the way, the correct coordinates for the vertices of an icosahedron inside a unit sphere are:
Sometimes Linux wants to open files. I mostly use the command line, so I wrote some helper programs to open things in terminals.
open-text-file
opens your default text editor in a terminal. I set it as my program to open all text files.open-directory
opens a terminal with that working directory. I set it as my program to open all directories.They’re both available in short-programs. Both default to xterm.
When you click an email address, it automatically opens in your email client. But I don’t have an email client, I use webmail. I wrote a custom handler for Linux.
First write a program to open mailto links. Mailto links look like “mailto:me@mail.com” or maybe even “mailto:me@mail.com?subject=mysubject&body=mybody“. Test it by hand on a few links. Mine (mailto-opener) composes a new message using my webmail.
Next, write a desktop file for the opener. Here’s one:
#/usr/local/share/applications/mailto-opener.desktop
[Desktop Entry]
Type=Application
Name=mailto: link opener (github.com/za3k/short-programs)
# The executable of the application, possibly with arguments.
Exec=/home/zachary/.projects/short-programs/mailto-opener %u
Note the %u in the Exec= line. That’s required.
Now update your system mimetype database. On my Arch Linux install, I run
xdg-mime default mailto-opener.desktop x-scheme-handler/mailto
Finally, restart your browser. Really. Firefox and Chromium/Chrome both cache mimetype openers.
A related opener I added recently was for magnet links, such as are popularly used for bittorrent.
~ $ cat /usr/local/share/applications/transmission-remote.desktop
[Desktop Entry]
Type=Application
Name=transmission-remote magnet link opener
Exec=transmission-remote <TRANSMISSION INSTANCE> -a
transmission-remote
is the name of a command-line Linux program. It connects to an instance of Tranmission (a popular torrent client) running on another machine.
I’ve been designing a keyboard and case for the zorchpad.
There are four pieces in the first iteration.
A top bottom base, to enclose the keyboard electronics.
A keyboard plate. The keys fit into the holes here. You type on the top, electronics go in the bottom.
A top plate. You see the screens, and switches through the cutouts. Otherwise, it keeps the behind-the-scenes wiring out of sight.
And finally, the top piece.
Here are the pieces in correct position. In the top will be the screens and battery. The bottom is a keyboard you type on. The whole things is meant to fold on a hinge, much like a laptop.
The same pieces, spread out.
There were many, many problems with the first design and the first print. I’ll talk about them (and my fixes) in my next post.
The Zorchpad needs a custom keyboard. Its power budget is only 1mW, and there’s just nothing available in that range. So, I need to make a custom keyboard. I started reading up on how to make your own–especially the electronics.
I don’t know how to make a PCB:
Or how to attach headers to the inside of an existing keyboard, which looks like this–:
But I found a project called GOLEM with an excellent guide to making your own keyboard. Here is their wiring:
I can do that! They got me out of a major rut.
Their advice walks you through how to do a small keyboard in a cardboard plate. I did a few keys, gauged the effort, and decided to use my 3D printer. Cutting out 50-60 keys precisely by hand doesn’t sound easy. Worse, if you mess up, you have to start over. In plastic, I can’t mess up halfway, and the spacers to support the keyboard can be part of the print.
Above, I’m designing a “sampler” keyboard in CAD (OpenSCAD). I want to iron out problems in my process before I try a full-size keyboard. Below, Prusa-Slic3r is slicing the finished model for my 3D printer to print.
Here’s the finished sampler keyboard:
Currently I’m waiting on keycaps and switches ordered from China, and then I’ll put together my finished keyboard. But I have been making some progress in the meantime. Here’s the layout I’m going to try.
And I’ve started streaming some development of a case and keyboard on Twitch (Tue/Thu 12pm noon, EDT). Feel free to join! Anyone can watch, but you need an account to chat.
My friend Callen tried to help me run a DC motor to roll my curtains up and down. We didn’t make a ton of progress, but we had some fun making a little music.
I’ve gotten to the point in Zorchpad development where I’d like to see how the whole thing fits together and if there will be any insurmountable problems. We’re still trying to figure out some things like–will it have one screen or two? What form factor will it be? Will the keyboard fold in half? So I put together a cardboard model.
This model has:
Immediately, a few problems pop out:
My next step will probably be to make a custom working keyboard. Then, I’ll make an entire working zorchpad. Both will be either cardboard or 3d-printed (whichever is easier).
Hello, Linux terminal users! Let me present you a simple feature you’ve all seen, but might not have noticed.
You’re on the terminal, and you open a text editor of chice–nano, vim, emacs, acme etc.
After you edit for a bit, you close the editor.
Now you’re back where you left off. My question is, how? How does nano remember what used to be on screen? How does it get restored? Is nano doing this, or bash?
Well, I took at look at the source code to nano. Then I thought, “whoa! that’s way too complicated.” So I found a much simpler project called ted someone made to educate themselves. That was also a little complicated, but both seemed to use ncurses. So I wrote the following simple program, which also displays something and then restores the screen. Even though it’s very simple, it still works.
// Compile with: gcc -lncurses editor.c -o editor
#include <curses.h>
#include <stdio.h>
int main(int argc, char **argv) {
initscr();
refresh();
printw("Hello world");
getch();
endwin();
return 0;
}
Aha, so it’s something in ncurses, maybe. Let’s dive deeper.
So initscr() presumably saves the state in some fashion. endwin() definitely restores it, because if we comment that out, the terminal stops being restored. Since initscr() probably does lots of other irrelevant logic, we could take a look at endwin() to dive in. But let’s do something even simpler first.
As background, the linux command line is pretending to be an obsolete piece of hardware called a terminal. Specifically, it’s pretending to be a model called the DEC VT100 (or a later one, but they’re mostly backwards compatible). The terminal accepted text over a wire, and printed it to the screen.
When it got special text, it would do special things. These are captured today as “escape codes”–special non-printable characters, which cause your software terminal to also do special things. What kind of special things? Well one example escape code is “Backspace”, which deletes the last character. Another code is “\r\n” (carriage return; new line), which goes to the beginning of the line, and down one.
I suspect the answer to what’s happening with save and restore of my terminal might be some magic escape codes. So let’s just redirect the output to a file, and see what data is being center over the virtual wire to our virtual terminal.
$ ./editor >magic.txt
$ xxd < magic.txt
00000000: 1b28 421b 2930 1b5b 3f31 3034 3968 1b5b .(B.)0.[?1049h.[
00000010: 313b 3530 721b 5b6d 0f1b 5b34 6c1b 5b48 1;50r.[m..[4l.[H
00000020: 1b5b 4a48 656c 6c6f 2077 6f72 6c64 6a1b .[JHello worldj.
00000030: 5b35 303b 3148 1b5b 3f31 3034 396c 0d1b [50;1H.[?1049l..
00000040: 5b3f 316c 1b3e [?1l.>
Well, that’s certainly a bunch of magic. Now something cool happens:
$ cat magic.txt
This command does nothing visible. It doesn’t print “Hello world”, even though that’s in the file. In other words, it’s printing Hello world, then really quick resetting the terminal. Just too fast for my poor human eyes to see.
We’ve confirmed the escape code theory! This file has everything we need. We can look at the source code to ncurses if we’re curious, but we don’t need to (and I won’t).
One thing I immediately see in this file, is that it doesn’t seem to contain the words that were on screen. So it’s not that the program read what was on screen, and printed it back later. Rather, there are some magic escape sequences happening to save and restore the terminal.
Okay, so somewhere in those 70 bytes is a magic code or two we want. Let’s examine all the bytes.
What kinds of escape codes appear here? Hex 0x1b is ESC, basically the escape sequence–it cues the terminal in that a special escape code is coming. 0x1b9b ( ESC followed by [) is the CSI escape code. DEC private codes refer to other escape sequences used by the DEC terminals like the VT00 (I’ll just shorten this to “DEC” below).
Without further ado, let’s break down those 70 bytes. Apologies for any errors below–correct me in the comments.
OK, solved. The magic save bytes are 1b 9b 3f 31 30 34 39 68 (<ESC> [?1049h). The magic restore bytes are 1b 9b 3f 31 30 34 39 6c (<ESC> [?1049l). And xterm or tmux is doing the save/restore magic, based on seeing this escape mode.
Hmm, how minimal can we get a working file, I wonder?
#!/bin/sh
echo -ne '\x1b[?1049h' # Save terminal
echo -ne '\x1b[H' # Home the cursor
echo "Hello world"
sleep 1
echo -ne '\x1b[?1049l' # Restore terminal
Yep. That works fine.
ANSI: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
DEC: https://vt100.net/emu/ctrlseq_dec.html
DEC: https://vt100.net/docs/vt220-rm/chapter4.html#S4.6.18
xterm’s control sequences: https://www.xfree86.org/current/ctlseqs.html
I hacked up a little to-do app in an hour. The emphasis is on focus.
It’s linux only. You can find it in my short-programs repo on github.