# Building the m103. I'm in the process of building a "neo-retro computing slab" (née "cyberdeck") for note taking and second brain activities. The purpose of this page is to document the process, how I've resolved the dozens of issues that I've come across, and the outstanding issues I still need to address. **==Note: This page will not be finished until after the device is finished, probably mid-2025==** ## Defining m103 ### What's with the "m103" name? I've always thought that the [TRS-80 Model 100](https://dathsgarage.dk/retro-computer-collection/computers/others/tandy-radio-shack-trs-80-model-100/) ("m100") portable computer was an interesting device. Released in 1983 at $1,399 ($4,400 in 2025 dollars), and at the time other computers took up half of a tabletop, it was about the size of two 13-inch MacBook Pros stacked on top of each other: ![[m103-hero.png]] The Model 100 was fairly popular with a certain crowd, such as news reporters who would use them to write their stories while still in the field and submit in the moment via an acoustic coupler modem connected to a payphone. They ran on AA batteries, and had surprisingly good displays and keyboards. I've been wanting to build a device for writing and general second-brain type work, and got to thinking that the m100 form factor might work out great for my needs. As far as I can tell, the Model 100 was followed by a Model 101 and a Model 102, but never a Model 103 – so I'm calling mine the m103 in honor of these neat little devices. ### m103 goals ==In process== - Easily access my accumulated files (notes, reminders, references, etc.) including global search - Easily capture information, create new files (log files, writing, etc.) - Primarily offline, but with file synchronization to my laptop; no reliance on cloud services - Secure - Battery powered with at least four hours of run time - Visual throwback to the m100, but not attempting to duplicate it exactly; very high build quality to approximate a 'real' production device - Ability to use almost entirely by keyboard, without requiring a mouse or touchpad - GPS tagging of notes ### A wide-screen display One of the most prominent things on the Model 100 is that widescreen LCD display. I wanted to get something that was visually similar, but up to modern display standards. After a lot of searching I ended up buying the "[8.8 inch Stretched Bar Wide Touch Screen Monitor 480x1920 IPS Long bar LCD Display Secondary Screen PC Case for Windows Rpi4](https://www.amazon.com/dp/B0B1H5F11Z)" display from Amazon. It's a 480×1920 (yes, portrait by default) IPS display with a decent contrast ratio (800:1) that can get reasonably bright (600cd/m²). The display itself is 8.8" diagonal, but that number is deceiving due to the aspect ratio, as the display is only 2.15in/55mm × 8.62in/219mm. When it arrived, it smelled very, very musty. I was surprised I didn't see mold growing on it somewhere. I guess that's why most products include those little silica gel packets in the box. Fortunately, the smell went away after a day or two, and since then the monitor has been fine. ### A custom, retro keyboard Gaze again upon that Model 100 keyboard: ![[m103-keyboard.png]] It's a thing of retro beauty, and amazing for its time: full-sized keys, deep key travel, the slashed zero, square brackets, an embedded number pad, and the amazing (now) retro font. Swoon. (By the way, if you're into the history of keyboards, check out the [Shift Happens](https://shifthappens.site/) website and try to get your hands on a copy of the now sold-out two volume set.) Since the keyboard is such an iconic part of the Model 100 design, I set out to create my own keyboard in homage to the original one, but with updates to take it into the modern era. Also, I wanted to reduce the overall number of keys to make the device smaller than the Model 100. Fortunately, I ran across the [FK Keycaps](https://fkcaps.com/) website where you can design your own keycaps, including uploading your own typeface and exactly position the elements on each key. I played with their keyboard designer for a good long while, and landed on this design: ![[m103-mykeys.png]] Most keys have at least four functions: the lowercase version of the character ("j"), the uppercase version ("J"), the symbol on the upper left ("«"), and the symbol on the upper right ("»"). The physical layout – such as the offset between rows 1 and 2, and rows 2 and 3 – is close to that of a Mac keyboard, which is very, very familiar to my fingers. My design includes a bunch of details that I'm really excited about: | Key | Description | | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Zero | If you're going to go retro, you've got to have a slashed zero | | :) | Will bring up a panel of my favorite emoticons/emoji | | ™ | I use this sometimes for soft sarcasm, saying things like Best Answer Ever™ | | ₩ | Symbol for the South Korean Won. I'll explain why (way) below. | | ə | International Phonetic Alphabet symbol for unstressed vowels. One of my favorite college classes was linguistics, where we used this symbol heavily. | | ß | My Dad spoke bits of (non-native) German when I was young, and I liked it | | Đ | A somewhat obscure Spanish symbol that means "de". I lived in Spain for a while when I was young, and I remember seeing this on signs for banks, like the "BANCO Đ ESPAÑA". | | » | I use this symbol to make it easier to find important files. For instance, on the Mac, "» tasks.md" will sort to the top of an alphabetic list in Finder. | | ¶ | Sometimes I'll pull several paragraphs into one to save vertical space, and use the pilcrow to indicate the breaks between them [^2] | | § | I like to use this sometimes for footnotes, plus I like how it looks | | Ç | Reminds me of my language immersion courses in rural France during college; also great for loan words like façade | | √ | Love this for indicating that things are complete. Feels so good. | | × | When indicating dimensions (like 10×10mm) or multiplication (a×b) it just looks so much cleaner than using an x | | Ñ | Critical to differentiate between begonia the plant and Begoña the woman | | Ɲ | Nasal n, used at the end of the native American name my father gave me | | P A CAP | No, not capitals. CAP is for capture, P is for Photo, and A is for Audio. | | SUPER | Linux keyboards sometimes have "SUPER" instead of the Windows icon or the Mac Command key, so I decided to reference that | | IZQª | Spanish-like abbreviation for "izquierda", or left; used for the upper-left key symbol | | NEU | German for "new". Used to create a new note from anywhere on the system. | | FINNA | Icelandic for "find". I love [[Iceland]], so I had to reference it here somewhere. | | DERª | Spanish-like abbreviation for "derecha", or right; used for the upper-right key symbol | | ← B → | Used to adjust brightness of the display [^3] | | ← V → | Used to adjust volume [^4] | | ‡ | I forgot to add this one! I'll have to put it as a key combination somewhere. | For US$59.60 including shipping, I was able to get 46 XDA keycaps laser-etched to my specifications, delivered to my front door 10 days later. Modern shipping is amazing. | Date | Where | What | | ---------- | --------------------------------------- | ------------------------------ | | 2024-12-27 | The internet | Order placed on their website | | 2025-01-02 | Shah Alam, Kuala Lumpur, Malaysia | Order picked up | | 2025-01-02 | Sepang, Malaysia (KL Airport area) | On the way | | 2025-01-03 | Singapore | In transit | | 2025-01-04 | Sennan-Shi, Japan (Kansai Airport area) | In transit | | 2025-01-04 | Oakland, CA, USA | International shipment release | | 2025-01-06 | My house | Delivered | And with that, they arrived in my mailbox: ![[m103-keycaps.jpg]] They are fantastic – just what I had imagined that they would look like. Nice job, Simon and team at FK. Very well done. One afterthought: I should have ordered one or two more keycaps without any caption, in case I break or lose one of these. In case you're wondering, the typeface is [National Park Typeface](https://nationalparktypeface.com/) by Andrea Herstowski, Ben Hoepner, and Jeremy Shellhorn. In their own words, it "captures the charm of the router-carved type ubiquitous in America’s national parks, without sacrificing legibility or versatility." I love how it provides a nicely structured overall look, feels approachable due to the rounded ends to each stroke, and mirrors the feel of the original Model 100 keyboard typeface. (For a deeply-researched page on a similar typeface, check out [The Hardest Working Font in Manhattan](https://aresluna.org/the-hardest-working-font-in-manhattan/)). There's a social group at work called the "Loud Clickers". I posted a message to see if anyone had a switch tester that I could try out, and a guy named Vik pointed me to his. Several hundred pecks later, and I chose "Gateron Silent Red" as my switch of choice: silent, but deadly. Just like me. ### A bespoke LCD font One of my favorite things about older devices like these are the fonts that they use. They didn't have the luxury of so-called Retina or 4K displays, and every pixel cost money. Typically, characters were fairly rudimentary, with dimensions of 5×7 or 7×9 pixels – which sometimes led to strange jumps in the baseline for characters with descenders like "jpqy", or vertical squishing for capital letters with diacritical marks, like "Á". I wanted to echo that pixel font look for m103, but also fix those issues and others. I looked around for a suitable bitmap font and found several good ones, like [Pixel Operator](https://www.dafont.com/pixel-operator.font) by [Jayvee Enaguas](https://tilde.club/~harvettfox96/), but unfortunately couldn't find exactly what I wanted. So, I discovered the nifty-but-weird [BirdFont app](https://birdfont.org/) and used it to create my own font: ![[m103-font.png]] ↑ My font This way, I could get the retro feel that I want, while having individual control over characters like the zero (dotted), arrows (important to my notation system), and accented characters. A lot of work, but well worth it. For most of the characters, I stayed on a standard pixel grid, but in a few places I cheated with pixels shifted 1/2 unit horizontally or vertically. The uppercase "M" is one of them – see if you can find some of the others. All that said, there still seems to be some artifacting with the fonts when displayed; sometimes I can see faint lines between the different sections of the characters – I tried editing the .bf file directly to round off the coordinates (e.g. from 40.0625 to 40), but that didn't seem to help: ![[m103-font-artifacting.png]] ↑ Examples of artifacting: see the "e", "g", lowercase "L", and "m" **==Font next steps==** - [ ] Sort out why my fonts have artifacts in them ## 02 Picking my brain ### Bye, bye, Raspberry Pi? Last year, I built a device designed to help me "capture the moment" while traveling. With the help of a native Japanese speaker, I named it "Shukiri", derived from the phrases "しょきり" or "Shokiri" for "capturing the moment" and "瞬間を切り取る" or "Shunkan o kiritoru", literally "to cut out the moment." With a single command, that device had the ability to capture a standard photo, a 180º fisheye photo, a 10-second audio clip, the GPS location, a text note including tags for who I was with and what I was doing, and a variety of sensor readings like air pressure, humidity, and UV. I built Shukiri on top of a Raspberry Pi 4B, a small touch screen, a 2TB SSD, and a bunch of cabling, blood, sweat, and tears. I took it on an extended vacation throughout Europe, but eventually abandoned using it – primarily due to one reason: whenever I wanted to capture a moment, I'd have to wait for a 90-second boot sequence, and the moment would have passed. ### Intel inside? So one of my first priorities for m103 was to build it on top of a platform that I could easily suspend and resume at a moment's notice. And then I remembered: I had a 2012 MacBook Air 13" with a 1.8GHz Intel i5 and 4GB of RAM with a broken screen, just sitting on a shelf. I had looked into repairing it previously, but the cost of a used screen was more than the entire value of the laptop. While it's significantly slower than today's Apple M-series chips, it's more than enough for my needs. Let's see if this works. Next, I wanted to see if it would even be possible to fit the motherboard into the new form factor. For the m103, I'm targeting a width of 256mm[^1], although I'm open to going up to 300mm, the size of the original. According to Apple, [the width](https://support.apple.com/en-us/111966) of the MBA13 is 325mm – much wider than my target. I didn't have the donor laptop with me, so I turned to the one true resource: ifixit.com and their MacBook Air 13" Mid 2012 Logic Board Replacement [page](https://www.ifixit.com/Guide/MacBook+Air+13-Inch+Mid+2012+Logic+Board+Replacement/10957). I was disappointed to see that the motherboard assembly ran the entire width of the laptop. Was I out of luck? ### Will it b\[l\]end? I zoomed in on the motherboard and noticed that the assembly was actually in three pieces: the motherboard, the fan, and another smaller board to the right. If I could separate these parts, would it be possible to bend the board over to fit into my build size? I downloaded an image of the motherboard assembly, placing it into a Keynote document and setting the width to exactly 325 pixels. From there, I could measure the width of the main board. And, amazingly, it looked like it would work. Once I got back home, I got right to tearing down the donor laptop, starting of course with detaching the battery, followed by detaching the display cabling, antennas, keyboard, and trackpad. Outside of the laptop, the motherboard worked just fine when connected to an external monitor, keyboard, and mouse. And, just as anticipated, it would be possible to separate the motherboard assembly into three parts. Perfect. That said, the battery is another issue. It's a single unit, made up of four individual cells. And unfortunately, it's much too wide for my target size. ![[m103-battery-fold.png]] ↑ My battery folding goal After close inspection and several Reddit posts and responses, I figured out that – if I was sufficiently careful – I could release the rightmost cell from the casing, gently fold the connected cabling 180º to the left, and have it sit on top of cell number three. ![[m103-spicy-pillow.png]] ↑ The spicy pillow I am generally a very precise person when it comes to working with my hands. Not this time, however. I started out right, using a length of dental floss to separate the cell from its sticky backing, but when I flipped it over and started to peel away a sticker for a better view, I must have nicked the cell. As smoke started to trickle out, I grabbed it and ran to the front door, setting it outside and watching helplessly as cell number four turned into a nice [spicy pillow](https://www.reddit.com/r/spicypillows/). Well, crap. I decided to worry about power later, and move on to other parts of the build. ### Slow. So very slow. To fit into my target width, I'd also need to remove the heat pipe (and old thermal paste). I know that's critical to keeping the processor at a reasonable temperature, so I designed and 3D printed a duct that sits over the motherboard and channels air from the fan (now rotated 90º CCW) across the CPU, GPU, and SSD. I put adhesive-backed Raspberry Pi heatsinks on top of the CPU and the GPU, and turned it on. And ... it ... was ... so ... incredibly ... frustratingly ... slow. I pulled the adhesive-backed Raspberry Pi heatsink off the CPU, removed all the sticky residue, added some fresh thermal paste, reassembled it, and booted. Outcome? Nothing changed. I was pretty convinced that it was still a thermal throttling issue, where the CPU is constantly slowing itself down so that it doesn't melt into a blob of metal, but wanted to learn more. I got out a Flir thermal camera that I bought several years ago to try and troubleshoot insulation issues in my house, and checked the board. Air coming out of my ductwork was at about 32ºC and the heatsinks were around 40ºC. The rest of the motherboard seemed ok. That, too, seemed ok. Maybe, though, the thermal camera wasn't giving me a good reading of the internal temperature of the CPU die. I tried downloading a couple of apps that could give me a CPU temperature reading, but had a bit of difficulty getting them to work (influenced in no small part by how slow the computer was). Frustrated, I wanted to make sure that something wasn't more seriously broken, so I took a different approach. I carefully applied fresh thermal paste, re-attached the heat pipe and the fan in their original locations, and put the assembly back into the keyboard portion of the case. I reattached the keyboard/trackpad ribbon cable, and nothing else, and booted the laptop. Solved. It booted right up, ran quickly, and the fan stayed at a quiet 2000 rpm. Long story short, it appears that there's a thermal sensor built into the circuit board for the trackpad. As long as that's connected to the motherboard, the CPU stays around 45ºC under normal loads – even without a heat pipe, thermal paste, or heat sink. ### Whither AI It seemed like I had the thermals sorted, but I wanted to make sure. And what better way to push the processor than to run some LLM queries on it? I'm not looking for m103 to be an AI-driven device, but it might be nice sometimes to be able to quickly look up why the sky is blue or the thickness of a human hair. I like to think of AI as a drunken uncle: somewhat accurate some of the time, completely off base other times, but at the end of the day it is sometimes helpful to get started on a topic. However, as m103 is supposed to be a primarily offline device, I don't want to have to call out to the internet each time I have a query. So first, I wanted to see if I could get it working on my development laptop. I downloaded [Ollama](https://ollama.com/) and Meta's [Llama 3.2](https://ollama.com/library/llama3.2) model and successfully ran a few test queries at the command line. I'm planning on writing some software for this device, so I wanted to see how easy it would be to pull Ollama responses from the command line into an app. I created a test app in Xojo that opens a shell upon launch, and then keeps it open while the app is running. I can type a question into a text box, which is then fed to Ollama via that shell, and the response is returned to Xojo and displayed in a window. It works well enough for a proof-of-concept, although the output contains a lot of control character garbage that I need to remove: ``` \[?25l⠋ \[?25h\[?25l\[2K\[1G⠹ \[?25h\[?25l\[2K\[1G⠹ \[?25h\[?25l\[2K\[1G⠸ \[?25h\[?25l\[2K\[1G⠼ \[?25h\[?25l\[?25l\[2K\[1G\[?25h\[2K\[1G\[?25hOn average, the diameter of a human hair ranges from about 50-150 micrometers (μm). However, it's worth noting that this can range from around 20-200 μm, with an average thickness of around 70-80 μm for most people. \>\>\> \[38;5;245mSend a message (/? for help)\[28D\[0m ``` When I tried to recreate this on the MBA13 motherboard, however, I ran into another glitch: that motherboard only supports up to macOS Catalina, and Ollama needs macOS Big Sur. I'm pretty sure that there's a rabbit hole I could go down to get Catalina working, but I took a pause instead. ### Abandoning chip At this point, the issues with reusing the MacBook Air board were starting to pile up, the Ollama issue being just one of many: I found out that here's [no way to cold boot](https://superuser.com/questions/603710/can-i-power-up-a-mac-with-a-keyboard-shortcut) an MBA13 from an external USB keyboard; it has to be done via an internal keyboard or by unplugging and replugging power to the device. Ugh. A coworker of mine pointed out that I won't be able to run the MBA13 on just three cells, as it needs all four cells to provide sufficient voltage. So, I'd have to buy another battery assembly, and then try my hand at folding it again. And, after having reminded myself first-hand about how volatile those batteries are, I'm not really inclined to keep messing with them, especially since this device will be going places with me on planes. Finally, since I don't have an LCD panel connected to the internal display connector, there's the entirely real possibility that I would get into an unbootable state where I'd need to reattach the (broken) internal monitor back to the motherboard to get it to boot. Fine if I'm at home, but not good if I'm on a trip. ### Return of the Pi So I decided to take a shift in tactic, and went back to the Raspberry Pi 4B. Fortunately, there's little impact on the software that I want to use, because both Obsidian and Xojo apps can run on that platform as well as macOS. I set up the Pi, installed Raspberry Pi OS on a microSD card, and booted without incident. However, it felt a bit slow compared to last time I used the Pi. Running the [Raspberry Pi Diagnostics](https://www.raspberrypi.com/news/sd-card-speed-test/) app showed that that the card was too slow, so I used the SD Card Copier app to move my installation to a faster card. At times it feels like every step in this build has a caveat, but that's part of the fun? Right? I want m103 to be able to hold a significant amount of information – for example, ideally a mirror copy of our family photos, an offline copy of Wikipedia, and perhaps an LLM. I have an external 2TB Samsung SSD from the previous project that I wanted to reuse, so I plugged that in and used Add/Remove Software to install gparted-1.3.1-1 (64-bit) ([src](https://raspberrytips.com/format-mount-usb-drive/)), delete the old partitions, and create one new large partition. Success! Now my Pi has 2.0625 TB of space to work with. Next, I grabbed all the parts – plus the display I'm going to use for the build – and went downstairs to watch TV with my wife. Plugged it all back together just as before, plus the display, and ... it didn't work. Every time I plugged in the external drive, my Pi would reset the USB bus. After (much) troubleshooting while (not really) watching Vera on Britbox, I figured out that the difference was the portable monitor. Whenever I plugged in both the portable monitor and the external drive, it appeared to be drawing too much power from the USB bus. I reduced the portable monitor brightness and that appears to have solved it. ### Full-disk encryption I'm planning on taking this device with me on my travels, as a way to have my second brain with me, and as a device that I can use for writing and planning. As such, I don't want to have all of my data just sitting there for anyone to access if they snatch the device and pull the drives out. With the macOS board, full-disk encryption would have been built-in and very easy to enable. With Raspberry Pi, it's a different story, because it's not built in to the base install. With a bit of searching, I came across something called [BerryBoot](https://www.berryterminal.com/doku.php/berryboot). It allows you to encrypt almost the entire SD card, and then at boot time it inserts a shim OS to decrypt it and then hand over control to the Raspberry Pi OS. I was surprised to see that the default Raspberry Pi OS option was from November 2020. Fortunately, according to [these instructions](https://www.berryterminal.com/doku.php/berryboot/adding_custom_distributions), it's possible to create your own install, so I went to the Raspberry Pi [download page](https://www.raspberrypi.com/software/operating-systems/) to grab the latest version and convert it. A little bit later, and my device was running the latest version of Raspberry Pi OS from an encrypted SSD. Perfect! Well, almost perfect. There's one issue I ran into later: The BerryBoot OS doesn't seem to support the weird screen size of my display. When I plug it into my desktop display, I can see the entire boot process just fine. But when it's plugged into the portable display, it's just black. I figured out I can boot, wait about 10 seconds, type in my password (blind), and then a few moments later it'll go ahead and drop me into the Raspberry Pi OS desktop. Maybe something to look into later, but for now it's a nice theft deterrent. Now, on to the external 2TB SSD, which I also want to encrypt. Back to GParted, where I deleted all of the old partitions off the drive and started fresh, and then did the following according to the instructions found [here](https://medium.com/@xcxwcqctcb/raspberry-pi-external-hdd-encryption-and-auto-mount-tutorial-894390e15acc): ``` sudo apt update sudo apt install cryptsetup sudo cryptsetup --verify-passphrase luksFormat /dev/sda -c aes -s 256 -h sha256 sudo cryptsetup luksOpen /dev/sda securebackup sudo mkfs.ext4 /dev/mapper/securebackup sudo mkdir /mnt/bigssd sudo mount /dev/mapper/securebackup /mnt/bigssd systemctl daemon-reload sudo chown $USER:$USER /mnt/bigssd sudo dd if=/dev/urandom of=/root/luks-keyfile bs=512 count=4 sudo chmod 0400 /root/luks-keyfile sudo cryptsetup luksAddKey /dev/sdb /root/luks-keyfile sudo nano /etc/crypttab → add this line to the crypttab file: securebackup /dev/sda /root/luks-keyfile luks sudo nano /etc/fstab → add this line to the fstab file /dev/mapper/securebackup /mnt/bigssd ext4 defaults 0 0 ``` Time for a reboot for good measure to make sure everything is working correctly. And it is! When it first boots, I get asked by BerryBoot to provide a password to decrypt the MicroSD card. Once that's encrypted, it starts the boot sequence for Raspberry Pi OS and asks for the password for the external 2TB SSD. Only after all of that is done does it boot into the desktop. And, finally, when I go into /mnt/bigssd in File Manager, I can see the newly encrypted drive. Time to rejoice, for I have a 2.064TB encrypted Raspberry Pi. (But not for long – read on...) ### Sidebar: Power draw Any good project needs a series of random sidebar problems, this one included. In reusing my Raspberry Pi 4B from a previous project, I was able to also reuse my "[Pisugar2 Plus Portable 5000 mAh UPS Lithium Battery Power Module Platform for Every Raspberry Pi 3B/3B+/4B Model Accessories handhold(Not Include Raspberry Pi)](https://www.amazon.com/gp/product/B08D8PPCKN?ie=UTF8&psc=1)" (got to love those Amazon product names designed to show up in any conceivably-related search). This board provides both battery power and a real-time clock to the Raspberry Pi. Up until this point, I was powering the Raspberry Pi from that board, while also having that board connected to a 5V 3A wall charger. I decided that I wanted to see how much power the Raspberry Pi was drawing, to get a sense whether that battery would last long enough when also driving the display. So, I removed the battery, plugged the wall charger into a USB [load tester](https://www.amazon.com/gp/product/B07DCSNHNB?ie=UTF8&psc=1), and then the load tester into the Raspberry Pi. And, upon booting, I saw it was drawing around 4.9v at 1.15a – but also got the dreaded [lightning bolt of weakness](https://raspberrypi.stackexchange.com/questions/57963/what-does-the-lightning-bolt-mean#57965). Weird. I tried another (much more powerful) wall charger. Same thing. Tried it without the USB hub that I was using. Same thing. What was the difference? I had disconnected the PiSugar to test the direct current draw. When I plugged that back in, everything went back to normal. No more lightning bolt. For now, seems like it's good – but I'm wondering if I'll run into issues down the line. I'll have to wait to see. ### Battery gauge Speaking of the PiSugar, next I wanted to be able to see how much charge the battery has at any given time. I went to github and found instructions on https://github.com/PiSugar/pisugar-power-manager-rs: ``` sudo raspi-config → At the Interface Options menu, choose I2C, and Yes wget https://cdn.pisugar.com/release/pisugar-power-manager.sh bash pisugar-power-manager.sh -c release → Then choose PiSugar 2 Pro ``` After that, I went to `0.0.0.0:8421` in the browser and ... nothing. I did notice that I was getting an "unexpected argument 'filed:-1'" error when I ran raspi-config, so I tried updating that. What I didn't realize is that this also updated pretty much everything on the Raspberry Pi, or so it seems: ``` sudo apt update sudo apt upgrade raspi-config ``` About 20 minutes later, and ... nothing. I tried a full cold boot cycle to see if that helped. Still nothing. Next, I pulled up the [detailed instructions](https://github.com/PiSugar/PiSugar/wiki/PiSugar-Power-Manager-(Software)) to see what else I could learn: `` sudo systemctl status pisugar-server Ah-ha. That says I2C is not connecting to the board at all. I decided to skip the raspi-config app and just enter the command directly to enable I2C: `` sudo raspi-config nonint do_i2c 0 That gave me an error: "* Failed to find overlays directory". Weird. I went ahead and created an empty overlays directory at /boot/firmware/overlays, and ran the command again. This time the command ran without error – and when I go back to the Power Management page, it works! That process was somewhere between annoying and rewarding. Next, I updated the Safe Shutdown feature to Battery Level <= 5% with a 30 second delay, and updated both the RTC and SYS time from the web. While I was at it, I also did ``sudo raspi-config`` again and set the timezone, as that hadn't taken properly during setup. ### Sidebar: Pete and Repeat were sitting on a bridge I took a moment here to try and install Obsidian, the app that I'm going to be using for my second Brain on this device. I went to obsidian.md/download, then scrolled to Linux and selected the "AppImage (AArch64, ARM64)" version. However, I got an error when I tried to run it – I had unwittingly installed the 32-bit version of Raspberry Pi OS, but Obsidian needs the 64-bit version. > "Pete and Repeat were sitting on a bridge. Pete fell off. Who was left?" "Repeat" "Pete and Repeat were sitting on a bridge. Pete fell off. Who was left?" "Repeat" ... So, I'm starting over on the software side of the build. First, I tried redoing BerryBoot but with a modified 64-bit Raspberry Pi image. That didn't work. Then I tried BerryBoot and downloading the 64-bit image from 2020, but BerryBoot wasn't cooperating. Then I tried this https://rr-developer.github.io/LUKS-on-Raspberry-Pi/, twice. Both times it booted into a black screen with a blinking cursor. Then I tried https://plentyofhacks.com/2020/raspberry-pi-4-boot-disk-encryption.html, which also led to a black screen with a blinking cursor. (Now I'm beginning to wonder if there's something else afoot with these blinking cursors. I don't think it's the SD card, because that will still boot when I'm not trying to do encryption.) After throwing away a not-insignificant chunk of my weekend trying to get everything working, I decided to take a step back and approach the problem from a different angle. I remembered that I had a 1TB [DataLocker DL-3](https://media.datalocker.com/manuals/dl3/DL3_DL3FE_UserManual.pdf) somewhere in the house that we used to use for our business. It's an external hard drive with a numeric keypad, running 256-bit AES encryption. I dug it out of my techno-archives, opened it, and replaced the original spinning platter drive with a 480GB 3.5" SSD. Within half an hour, I had Raspberry Pi OS running on it with full encryption. And the best part? It's much faster than the other solutions in part because the encryption/ decryption is being handled by the drive enclosure, not the processor on the Raspberry Pi 4S (commas added for clarity): ``` Sequential write speed 237,880 KB/sec (target 10,000) - PASS Random write speed 7,809 IOPS (target 500) - PASS Random read speed 4,609 IOPS (target 1,500) - PASS ``` This, combined with a much shorter boot sequence using Raspberry Pi OS instead of Ubuntu, means that boot times (and performance in general) are fast enough for my needs. ### Sidebar: Power draw (yes, again) So I've been doing additional battery testing to see how long this 10,000 mAh battery will last. I did a full drain today, and got just over 5h30m with off-and-on use and the screen always on, similar to a previous test. However, when I plugged the external battery into the wall and booted, it crashed during boot several times – likely due to a lack of amps again. On top of that, the display was flickering a bit. When I plugged it directly into the wall, it's good again. I'll have to noodle on this some more. **==Power next steps==** - [ ] figure out how to ensure I've got the amps I need when booting from a dead battery - [ ] https://www.reddit.com/r/RASPBERRY_PI_PROJECTS/comments/18wqlr2/powering_a_raspberry_pi_5_with_a_power_bank/?share_id=eacaBCVt9oARCqno9eHO8&utm_name=ioscss ## 03 It's alive, Jim 🎉 I let it run for several hours, and nothing failed or caught fire, so I'm feeling good. Finally. Now I can get back to the fun part of my build. ### File syncing I've been using Syncthing for several years now to keep my laptop and my [[galaxy fold|Samsung Galaxy Fold]] in sync. It's always one of the first things that I install on a new device: ``` sudo apt install syncthing ``` In brilliant contrast to everything above, it just worked. Granted, it took forever to sync – my two vaults tip the scales at something over 55GB, and the little Pi was sweating for a bit there – but I could move on to the next step. ### Obsidian.md As I mentioned above, one of my goals is to run Obsidian on this device. I returned to obsidian.md/download, then scrolled to Linux and selected the "AppImage (AArch64, ARM64)" version. After downloading it, I did a chmod +x on the AppImage file, and launched it. Success! At this point, I'm getting nervous that my next attempt at doing something is going to fail. Too many wins in a row. Got to keep the faith, man, got to keep the faith. ### Whether AI? When I worked on my previous "Shukiri" project, I decided to try out a local LLM to see just how capable the Raspberry Pi 4B really was. Surprisingly, it worked. Unsurprisingly, it was slow. Really slow. Like "12 minutes to answer why the sky is blue" slow. Now that I have a faster SSD driving this device, I wanted to try it again. If it performs even remotely well, it could be an interesting add-on to my second brain project. I've had luck with [Ollama](https://ollama.com/) on my Mac, so I'm going to try it again here using [these instructions](https://pimylifeup.com/raspberry-pi-ollama/): ``` sudo apt install curl curl -fsSL https://ollama.com/install.sh | sh ``` The install went well, with it reporting that the Ollama API is available on 127.0.0.1:11434. I'll have to keep that in mind for programmatic access; for now, I'l just be using the command line. Now that Ollama was installed, I needed an LLM to try it out with. Fortunately, I ran across [this article](https://itsfoss.com/llms-for-raspberry-pi/) that compares several models on a Raspberry Pi 5. While my performance will be slower with my Pi 4B, I'm anticipating that the relative speeds of one vs. the other will be the same for me. [Gemma2](https://ollama.com/library/gemma2) looks pretty good, so I'll download the 2 billion parameter model for a test run: ``` ollama run gemma2:2b ``` Damn, it required 3.3GB of RAM and I only had 3.0GB available. I closed Obsidian and ran Ollama again, and it started right up. In 2m57s, I got my answer. Much, much faster than the previous attempt, but still much slower than my Mac M1 at 9s. Verdict? Good enough for my purposes. Success. I want to be able to just type "gollama" at the command line, so I do this: ``` nano /Apps/gollama #!/bin/bash ollama run gemma2:2b chmod +x /Apps/gollama nano ~/.bashrc → Add to end of file: export PATH="$HOME/Apps:$PATH" source ~/.bashrc ``` ### Battery gauge, again Now that I'm on a fresh install, I need to configure the battery gauge again. I followed the instructions from above, and this time they worked. I updated the Safe Shutdown feature to Battery Level <= 5% with a 30 second delay, and updated both the RTC and SYS time from the web. Now, I wanted to see if I could get the battery percentage into the task bar, near the WiFi signal or Bluetooth indicator. I started with this [reddit post](https://www.reddit.com/r/pwnagotchi/comments/19exw3t/pi_sugar_2_battery_indicator_plugin/) that pointed me to this [YouTube video](https://www.youtube.com/watch?v=7m14hIfMFCU) from which I found this [github page](https://github.com/tahlly88/pwnagotchi-pisugar2-plugin/blob/master/readme.md) that I followed with slight modifications using comments from `JSGreenBoy` and `ooonst`: ``` cd ~ wget http://cdn.pisugar.com/release/pisugar-power-manager.sh bash pisugar-power-manager.sh -c release git clone https://github.com/PiSugar/pisugar2py.git git clone https://github.com/PiSugar/pwnagotchi-pisugar2-plugin.git sudo mkdir -p /usr/local/share/pwnagotchi/installed-plugins/ sudo ln -s ~/pisugar2py/ /usr/local/lib/python3.11/dist-packages/pisugar2 sudo ln -s ~/pwnagotchi-pisugar2-plugin/pisugar2.py /usr/local/share/pwnagotchi/installed-plugins/pisugar2.py sudo mkdir /etc/pwnagotchi sudo nano /etc/pwnagotchi/config.toml main.custom_plugins = "/usr/local/share/pwnagotchi/installed-plugins/" main.plugins.pisugar2.enabled = true main.plugins.pisugar2.shutdown = 5 main.plugins.pisugar2.sync_rtc_on_boot = true ``` Unfortunately, this doesn't work. I've [posted a question](https://www.reddit.com/r/pwnagotchi/comments/19exw3t/comment/m8ofda2/) on reddit to see what I can find out. **==Battery next steps==** - [ ] come back to the power manager and set up custom button functions - [ ] follow up on my [question on reddit](https://www.reddit.com/r/pwnagotchi/comments/19exw3t/comment/m8ofda2/) ### Onboard battery I wrote a script to log how long the Pi can survive on battery, and let it run as I went to bed: ``` #!/bin/bash LOGFILE="batterylife.md" while true;do CURRENT_TIME=$(date+'%Y-%m-%d:%H:%M:%S') echo "Time: $CURRENT_TIME" >> $LOGFILE sleep 600 done ``` With my external 10,000 mAh Mophie battery plus the 5,000 mAh PiSugar battery, I got about 4h45m with everything active: hard drive, USB hub, GPS dongle, and display. Not bad. Next, I plugged the 10k battery into the wall while leaving it connected to the Pi, and rebooted. All was well, until I tried running a query in Ollama. Despite being plugged into the wall, the discharged 10k battery and discharged PiSugar couldn't muster enough electrons, and the Pi crashed. I then tried two more batteries. First was an Anker PowerCore 20,000. That one, too, led to crashing under heavy load. Next, I borrowed my wife's 5,000 mAh Anker 733 GaNPrime PowerCore 65W; it was successful in not crashing under the LLM load, but drained in about 3 hours (mind you, the PiSugar was dead at that time, so it may have done a little better if both were charged to start with). Since that's her battery, I went back to my PowerCore 20,000. Perhaps I can live with being careful not to run CPU-heavy tasks right when I first boot after completely running out of power. However, I quickly discovered that battery cannot charge something else while it itself is being charged. So back to the original 10,000 mAh Mophie battery it is. ## Working on the case ### Angling the display On the m100, the display sits flat against the case, parallel to the keyboard. I want to keep that feel, but I also have realized that, despite it having a good viewing angle, I want to be able to angle it up when I'm using m103 for longer sessions. Aaaand, holy cow, in researching this I just realized that the top surface of the m100 is actually angled a bit. Nice, but not sufficient for this build. ![[m103-hingeoption.png]] ↑ Source: [Home Computer Museum](https://www.homecomputermuseum.nl/en/collectie/tandy/tandy-100/), The Netherlands; red line added by me Looking more closely, there's an indented line that goes all the way across the surface of the m100, just above the function key row. Perfect! I can build mine so that the entire upper section (see red dotted line) will hinge up when I need a better view. Now to figure out exactly how to do that. While researching the hinge idea, I suddenly thought: I've got to see if there's a way to emulate an original m100 on my m103. A [quick search](https://duckduckgo.com/?q=tandy+model+100+emulator&t=newext&atb=v449-1&ia=web) on duckduckgo says it's possible. I'll add that to the list of topics for later. The monitor comes with a sturdy metal surround, so I'll leave that in place. It's 233×66×14mm, and I'm going to have it stick up about 1mm above the surface of the device. What's most important to me is that, when I angle the display up, it doesn't introduce any extra space in the gap (where the long dotted line is in the above image). I played around with various geometries, always making sure that the pivot point was right at the seam between keyboard and display, such as these: ![[m103-hinges.jpg]] ### Function keys On the original m100, there is a row of 16 function keys between the keyboard and the display. Originally, I wasn't going to include those in my build, but I'm thinking it'll really help carry forward the retro vibe. Plus, I can hook them up to do various ... well, functions. ![[m100-function.jpg]] Realizing that I can just use the key switches I already purchased, and tie them into the overall keyboard circuitry, I decided to create 3D printed keycaps that mimic the m100 ones. Taking some rough measurements off of a photo, they appear to be about 16x5 mm. I downloaded a 1u key STL from [Newtle Kim](https://www.printables.com/model/73567-3d-printed-mechanical-keyboard-68-keys/files) and then imported it into Tinkercad. Once there, I placed a series of clear blocks around and overlapping the key, with the result of cutting it down to the size I want while retaining the "+" shaped connector underneath. I printed one out as a test, stuck it on the key switch, and it worked! Nice to get an easy win sometimes. Here's the [Tinkercad](https://www.tinkercad.com/things/aGmbc8N1LlN/edit?returnTo=%2Fdashboard%2Fdesigns%2F3d&sharecode=pyAQX8HHp9HQRv_TsCOEFfDuUIs1ZBEYOceKnu4cKIM) page for it. Later, once I started laying them out in my m103 Tinkercad model, I remembered that my build is narrower than the m100. As a result, I've decided to go with 12 keys across instead of the original 16. It'll keep the same look, but save me trying to figure out what to do with all those function keys eventually – especially since I've already included cursor keys (the right-most four function keys on the m100) in my qwerty layout. ![[m103-fn-evolution.png]] There were a few fun steps in getting the function key geometry right. I've learned to print test pieces as I go, working with just a small piece of the build at a time (as shown above): 1. Small sample piece of the shell around the left hinge and left-most function key 2. First pass at the function key, as described above 3. Removing unnecessary legs, and adding a shoulder (see below) 4. Testing keyswitch distances with the shoulder in place (see below) Regarding the shoulder: At this point, I realize that I didn't want my function keys to have as much key travel as the regular keys, so I needed to find a solution to that. I'm using a different set of switches ([Gateron Milky White](https://www.gateron.com/products/gateron-ks-3x1-full-milky-switch-feature?VariantsId=10405)) for the function keys that are ever so slightly more tactile. Looking them up, they have a pre-travel distance of 2.0±0.6mm and a total travel of 4.0mm max. Perfect! I can work with that. I decide to design the function key row so that each key is slightly pre-compressed when not being used. That way, when I do hit the key, there's less travel needed before it activates. Here's how I went about sorting this out: ![[m103-fn-compress.png]] 2a. Normal key 2b. Normal key, when pressed all the way 4c. Raise the keyswitch by 2mm, and add a 'shoulder' to keep the key from rising equally; now the switch is pre-compressed by 2mm [^6] 3d. When pressed, key travel is shorter by 2mm. Bingo! ### Keyboard surround With that settled, I decided to focus a bit on the keyboard base plate and surround. If you spend enough time in the keyboard forums online, you'll end up thinking that you need an aluminum, steel, or otherwise heavy and esoteric base plate. However, thanks to [u/bAdmArk](https://www.reddit.com/r/Keyboard/comments/1igpqo1/comment/mbf53gd/), it looks like 3D printing my baseplate can work out well. It took a few tries to get to the point that I had all of the dimensions where I liked them: I printed out a couple of tests that just included the left-most side of the keyboard (about 1-2 keys wide plus the immediate surround), and played around with those for a while. The first thing I figured out is that I want the keys to sit at about 2mm above the front of the device when fully pressed. But, more importantly, I realized that I had spaced the keys too far apart, by about 0.5mm. Very glad that I thought to print little sample segments of the case instead of trying to print the entire thing in one go. ![[m103-surrounds.png]] In the above image, you can see several of the refinements as I went along: 1. (Test of the display surround, rotated 180º) 2. Test of the keyboard surround, function key shell, hinge, and key spacing 3. Updated vertical key spacing: the bottom lip was too close to the keys, causing them to rub 4. Updated vertical key spacing: fixed the bottom lip, but accidentally removed the infill to the right of Del and Enter 5. Restored infill to the right of Del and Enter (As the build got more complex, I was having trouble getting the macOS Creality Print software to create good enough scaffolding for all of the overhangs and gaps, and I ended up printing more than one plate of spaghetti. Out of frustration, I looked around and came across UltiMaker Cura – which delivered! So, at this point, my workflow is to create the design in TinkerCad, export it as an `.stl`, import it into UltiMaker Cura, slice it with supports, export it as a `.gcode` file, import that into Creality Print, and print from there. Convoluted, but it works.) ![[m103-scaffolding.png]] ↑ Trying out the automated tree scaffolding feature in Cura. It's like magic. Right now, I'm printing with the filament that's already in my printer, listed as "ELEGOO Matte PLA Filament Matte Black 1KG, 1.75mm 3D Printer Filament Dimensional Accuracy +/- 0.02mm, 1kg Carboard Spool (2.2lbs) for Most FDM 3D Printers" on Amazon ([link](https://www.amazon.com/dp/B0CFV3WF7P?ie=UTF8&th=1)). When the top design is finalized, I'm planning on printing it with white PLA to approximate the color of the original Model 100 top shell, and then probably sanding, filling, priming, and painting it off-white. That said, someone at work today suggested I consider painting it orange, which could be awesome. Since my printer can only print up to 220mm x 220mm x 220mm, I can't just print the keyboard surround in one go. Instead, I'm going to have to print two pieces and connect them together later. Unfortunately, I can't just cut it in half, given that each key needs a stable surround and I'm using a staggered keyboard layout. (I thought very briefly about switching to an [ortholinear keyboard design](https://duckduckgo.com/?q=ortholinear+keyboard) to solve this, but no.) So, I fired up the 3d modeling program again, and painstakingly carved out a break line between the two halves: ![[m103-staggered.png]] In the image, you can see connectors that I'm going to use to help lock the two halves together (the image is rotated 90º). On the left, you can see both the tab and the slot that it will go into. On the right, you can see the tab but the slot is hidden in the yellow area. Oh, and as I was doing these prints, I ran out of filament and switched rolls. I'd never done that mid-print before, but it worked out fine. Kind of fun seeing the two colors in one print. As before, I printed out just this region of the keyboard base to make sure that everything aligns before printing the full version. And I'm glad I did, because I found several areas where I hadn't calculated correctly. ![[m103-base-edits.jpg]] It took a few generations to get to the final product: 1. First print, when I thought I had it all dialed in. Heh, no. 2. Fixed spacing to the left of the first column of keys 3. Adjusted thickness of the base where the keys snap in, from 1.5mm to 1.25mm 4. Refactored the layout and accidentally moved the left margin in for row 3 5. Fixed left margin, confirmed tolerances Ah! One other thing. After test-fitting, I realized that the tab-and-slot approach was going to be tricky to get right due to printing tolerances and PLA being a bit brittle. I removed all of the tabs and slots, and instead went with use glued-in metal rods to join the two halves: ![[m103-gluedrods.png]] I made the rods by clipping the pointy and "T" ends off of two nails, and used superglue to connect everything together. It worked pretty well in terms of alignment, and it seems strong, but I'm going to have to do something about the seam between the two halves. I may end up painting it. ### Making the top shell removable As I mentioned above, I'm planning on having the display hinged so that I can more easily see it. Another benefit is that it will allow me to reach inside the m103 and get at the parts. This'll be most important for access to the encrypted hard drive, since I'll need physical access to it to type in the password each time I boot. But the other reality of the situation, given that this is a self-built device based on a Raspberry Pi, is that I'll probably want access to all of the internals at one time or another. To that end, I'm thinking about making it so that the entire top assembly can be removed when necessary: ![[m103-top-shell-remove.png]] ↑ Left side of m103 To get this to work, I'm thinking about creating a tab that juts out of the keyboard assembly and interlocks into the bottom shell assembly (not to scale, obviously): ![[m103-interlock.png]] ↑ Left side of m103 showing slot cutaway When the display is raised, the tongue is out of the way and it's possible to drop the tab into the slot (note that in step 3, the display and keyboard are offset towards the left in the diagram). Then, once it's in the slot, I can push the keyboard into place (to the right in this diagram) until the tab fully anchors into the slot. At this point, I can also push the display back to its fully horizontal position, which will insert the tongue into the bottom shell – meaning that the top will be locked into position. I'll need to do some thinking around best lengths for the cables to the keyboard and display, but overall I think this'll work out well. As I was getting ready to print the display surround, I realized that it would be possible to print it as one large piece, rather than having to print two halves and glue them together. That's because, while it's 256mm wide, it's only about 12mm tall – which means I can print it at a 45º angle on the print bed and it'll all fit. It still remains to be seen if the change in angle will affect print quality: ![[m103-angleprint.png]] ↑ Nice try, no prize. Well, that would have been great. Instead, the end result was slightly tilted towards the back of the plate, the inner dimensions of the frame were slightly too small (maybe due to printing it standing up instead of laying flat), and it used up a ton of PLA to build the scaffolding: ![[m103-wasted.png]] ↑ Well, at least PLA is biodegradable (in [thousands of years](https://duckduckgo.com/?q=is+pla+biodegradable&t=newext&atb=v449-1&ia=web)) I ended up scrapping it, and taking another approach. I went back into Tinkercad and split the top into two sections (much like I did for the keyboard), and printed both independently. That worked, but now I have to deal with four visible gaps instead of two. For some reason, the hinges didn't end up being as smooth as the sample prints I made. I'm going to have to spend some time looking into this in more detail. Worse comes to worse, I'll have to cut them out and replace it with something else instead. But in any case, I'm pretty happy with where it's at, at this point: ![[m103-top.png]] ↑ Top shell with keyboard and display inserted ## Wiring the keeb Now that I have the upper shell in pretty good condition, it's time to focus on the keyboard wiring. There's a ton of information out there; I ended up referring to these: - MasterZen's [Handwired Keyboard Build Log](https://www.masterzen.fr/2018/12/16/handwired-keyboard-build-log-part-1/) - Matteo Spinelli's [Hand-wiring a custom keyboard](https://matt3o.com/hand-wiring-a-custom-keyboard/) - Christopher Swenson's [How to Build a 40% Keyboard](https://medium.com/@cglyph/how-to-build-a-40-keyboard-102b81fbf508) - Ben Chapman's [A Complete Guide To Building a Hand-Wired Keyboard](https://medium.com/cracked-the-code/a-complete-guide-to-building-a-hand-wired-keyboard-9d8c9cc7b041) - Blake Drayson's [3D Printed Hand Wired 40% Keyboard](https://ghost7.com/blog/3d-printed-hand-wired-40-keyboard/) - ScottoKeebs' [Handwired](https://scottokeebs.com/blogs/keyboards/scottoalp-handwired-keyboard), [ScottoKatana](https://scottokeebs.com/blogs/keyboards/scottokatana-handwired-keyboard), and [ScottoSlant](https://scottokeebs.com/blogs/keyboards/scottoslant-handwired-keyboard) keyboards - YARH.IO [Hand Wired 4x12 / 5x12 Ortholinear Mechanical Keyboard](https://yarh.io/cyberdeck-keyboard.html) I won't belabor the point too much, because there's already so much information on the web about hand wiring. At this point, mine looks like this; I still need to assemble and insert the 12 function keys, and then I'll be done with the per-key wiring: ![[m103-wired.png]] https://docs.qmk.fm/newbs_getting_started ``` sudo apt-get update sudo apt install -y git python3-pip sudo apt install pipx python3 -m pipx install qmk pipx ensurepath # restart terminal qmk setup # answer yes to cloning firmware; this will take a while mkdir ~/qmk_firmware/keyboards/m103 mkdir ~/qmk_firmware/keyboards/m103/keymaps mkdir ~/qmk_firmware/keyboards/m103/keymaps/normal qmk config user.keyboard=m103 qmk config user.keymap=normal qmk new-keymap qmk compile -kb m103 -km default ``` https://docs.qmk.fm/config_options https://docs.qmk.fm/newbs_building_firmware enable **Unicode Hex Input** by adding `#define UNICODEMAP_ENABLE` to your `config.h` file. Then, define the keycode using `UC(03A3)` for "Σ". https://docs.qmk.fm/keymap https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf https://docs.qmk.fm/keycodes_basic https://docs.qmk.fm/hardware_keyboard_guidelines https://docs.qmk.fm/porting_your_keyboard_to_qmk looks like i may have wired my keyboard upside down? https://www.dairequinlan.com/2021/01/the-keyboard-part-3-the-enwire-en-ing/ https://www.crackedthecode.co/a-complete-guide-to-building-a-hand-wired-keyboard/ https://golem.hu/article/pro-micro-pinout/ This helped me to understand the `config.h` format: https://github.com/DIYCharles/DIYKeyboards **==Keyboard next steps:==** - [ ] Program the board with my keyboard layout - [ ] Look into `pipx completions` in the future - [ ] Connect the board to my motherboard and test it - [ ] Look into ways to also use this as an external keyboard for my other devices, via USB **Self-Build Resources:** - QMK [Firmware](https://qmk.fm/) - r/MechanicalKeyboards' [Wiki](https://www.reddit.com/r/MechanicalKeyboards/wiki/index/) on Reddit - [ ] look into painting the PLA: https://www.youtube.com/shorts/FQmhZI0r32Y ### Look into USB-C hub I have a little Anker PowerExpand Direct 6-in-1 USB-C Media Hub A8362 that was originally designed for use with newer iPads. I'm wondering if I can use it with this build. I'm not using the USB-C port on the Raspberry Pi (power is coming in through the PiSugar instead), and I know there's a command I can issue to tell the Raspberry Pi to act as host on that port. Now I need to see if that will enable all of the ports on this little hub, especially MicroSD and USB. ==USB-C hub next steps== - [ ] find command to tell Raspberry Pi to become host - [ ] test all ports - [ ] confirm that plugging a wall cable into the USB-C PD-IN port won't bork anything - [ ] look into adding it to the build ## Taking advantage of the Pi platform ## Software development ### Trying Python I was originally planning on doing development for m103 in [Xojo](https://xojo.com/) (my hobby programming language of choice) on my Mac, and then compiling it for the Raspberry Pi ARM platform. I may still do that, but my son (a developer) recommends that I use something native to the Pi. I'm going to try out Python and see how that goes. I used Meta.ai[^5] to get the Python code for a basic text editor, and that worked straight away. However, the UI widgets look like they're out of an old Windows 3.1-Java-OS/2 mashup. While I'm going for retro, I'm not going for ugly. I asked Meta.ai for a recommendation for a modern-looking GUI; it recommended PyQt5 and successfully rewrote the code accordingly. While I'm not anticipating any commercialization of this device, nor a career writing Python GUI apps, I do want to make sure that any skills I pick up are as widely applicable as possible. Looking deeper, it [appears that](https://www.riverbankcomputing.com/commercial/license-faq) PyQt5 requires a commercial license in certain circumstances. I'm entirely on board with that, but it doesn't work for my specific needs. Another quick trip to Meta.ai says that the [GTK toolkit](https://www.gtk.org/) might be an option. I started by downloading the toolkit: ``` sudo apt update sudo apt install libgtk-4-dev python3-gi ``` With a couple of hours of back-and-forth with Meta.ai while watching TV ([Shetland](https://www.imdb.com/title/tt2396135/), a great detective show set in Scotland), I was able to get a little calculator application going. Here's the full Python [[m103-calculator code|calculator code]]. Between the text editor and calculator apps, (learning and) coding in Python is feeling promising for this project. Now, I wanted to see if I could get the Python code to appear in the apps menu on the Pi. Here's what I was able to sort (again using Meta.ai): 1\. Make sure the Python script starts with the correct shebang line: ` #!/usr/bin/env python` 2\. Create a `calculator.desktop` file, with the following content: ``` [Desktop Entry] Type=Application Name=Calculator Exec=python /path/to/your/calculator.py Icon=/path/to/your/icon.png Terminal=false ``` 3\. Make the calculator script executable, if it isn't already, and move it to the apps directory: ``` chmod +x calculator.py mv calculator.desktop ~/.local/share/applications/ ``` 4\. Open the Pi menu, choose the Other category, and click on your app. Et voilà, it works! - [ ] ==add screenshot of it here ### GPS integration When taking notes with my m103, I'd love for the ability to automatically capture my current location. Eventually I plan to write an app that lets me display both media and notes on a map – that way I could, for example, revisit a vacation based not only on photos and videos, but also by the notes that I took along the way. I have a little USB GPS dongle that I got off of Amazon for about $20 and used with the earlier Raspberry Pi project. I plugged it into my development Mac, fired up Xojo, and set out to write something that would talk to it. I created a new Xojo project and added in a SerialConnection control from the Library (4800 baud, 8 data bits, no parity, one stop bit), and added the following to the DataReceived event handler: ``` Var data As String = Me.LookAhead(Encodings.ASCII) If data.IndexOf(EndOfLine.Windows) > -1 Then data = Me.ReadAll(Encodings.ASCII) TextArea1.Text = data + TextArea1.Text end if ``` After a few minutes of the GPS listening for satellites, it got a lock. And placed me about a 30 minutes' drive from where I actually was. But that's good enough for now. I can refine it later when I test the code on the Raspberry Pi. **==GPS next steps==** - [ ] See if the GPS gets a better lock if I go outside - [ ] See if there's something in software I can do to improve the accuracy - [ ] Write software to GPS-stamp my notes when I create them ### 12 The command line ==Still to be written.== ### 12b Fortunes and .sig lines In my early days of computing, I spent many hours on text-based terminals connected to a central computer somewhere in the room or the building. At that time, the computers were typically beige-, taupe-, or putty-colored. The florescent lights had a cold, bluish tone. The computer rooms were cold, windowless, and isolated from the rest of the building by locked doors. And the screens were invariably green or amber phosphor on a black background. But there were little places where sysops injected some personality into that world: servers were invariably named after Greek gods, Norse gods, or references to Lord of the Rings or Monty Python[^8]. (Sometimes, these references would even help describe the network topology: a primary server named "Zeus" might control secondary servers named "Athena" or "Apollo".) Another source of personality was "fortune files" and ".sig lines". Sysops would collect various one-line quotes, sayings, jokes, and wisdom, which they'd accumulate into a text file. Then, when you first sat down at the terminal[^7] and logged in, you'd be greeted with a few lines of text: the system version, the last time you logged in, and a line randomly selected from the fortune file. Or, when you were sending an email, a random line from the file would be added to your signature at the bottom of the message – typically referred to as a "tagline". I thought it would be fun to bring something like that to life with the m103. As luck would have it, my digital packrat tendencies paid off yet again: Digging through my files, I found a fortunes file from sometime in the 1980s. I took a couple of evenings to go through it and clean it up: formatting, deduplicating, removing inappropriate content, and generally getting it ready for use. Reading through that file brought back a ton of nostalgia. There were a number of themes that stood out, perfectly describing the 1970s/1980s sysop personality, including: - Acronyms: `AAAAA: American Association Against Acronym Abuse.` - Anti-corporate: `A committee is a life form with six or more legs and no brain.` - Cats: `"A cat is only domestic so far as suits its own needs." - Heinlein` - Drugs: `Antacid: What ants use to get high!` - Geek humor: `54% of all statistics are made up. No, make that 82%.` - Intellectual superiority: `A duel of wits? I hate fighting unarmed opponents!` - Jokes: `A termite walks into a bar, and says, "Bartender?"` - Programming humor: `10 PRINT "Waiter, there's a bug in my LOOP": GOTO 10` - References to taglines: `----------- <Police tagline - Do not cross> ------------` - Society: `Always try to be a little kinder than is necessary.` - Star Trek: `"A joke...is a story with a humorous climax." - Spock` - Wordplay: `8 of 10 Americans suffer from hemorrhoids. 2 enjoy them?` As I was reading through those, I got to thinking. I didn't retype those lines. Each of those characters in the file represents a physical action: some sysop, hunched over some keyboard, somewhere on earth, pressed a key. That instant in time – when contact was made and the circuit was completed – was captured for as long as these files remain. With few exceptions, the keyboards and computers they were typed on are long lost, forever in landfills. And assuming the typists were in their 40s at the time, the Social Security Administration's Actuarial Life Table indicates that likely only 20% of them are still with us in 2025. But their ones and zeros live on – here's the full [[fortune file]]. ### Emulation - [ ] Get m100 emulation running on the m103 ## 13 Ten years of filing ==Still to be written.== ## 14 Obsidian as a nice markdown editor ==Still to be written.== [^1]: That is, in a nerdy homage to the lowly single byte, 2<sup>8</sup> millimeters. [^2]: Interested in the pilcrow? You've got to check out ==to do: find the book== [^3]: However, adjusting brightness on the display I bought is done through a little hole on the back of the case, so this will only be useful for external displays [^4]: I'm not planning on having a mic or speaker in the m103 device itself, so this would only be useful if I have Bluetooth headphones connected [^5]: Disclosure: I work at Meta, but not on the Meta.ai team. I use Meta.ai in part because I forgot my chatgpt password, and now I have to do the onerous step of clicking "stay logged out" each time I try to use it. [^6]: Yes, you're right. The tolerance for pre-compression is 2.0±0.6mm, so theoretically my switches could be already activated when compressed by 2mm. I'm going to hand-select switches that don't do that. [^7]: Typing that sentence dropped me into a rabbit hole of looking for a screenshot of a Digital VAX/VMS login prompt, which when led me to [this fascinating post](https://mansfield-devine.com/speculatrix/2016/03/vax-openvms-on-the-raspberry-pi/) by Steve Mansfield-Devine on running OpenVMS on the Pi. [^8]: Interestingly, it appears that the Python programming language was named after Monty Python, and "spam" came from a Monty Python skit about a restaurant that served spam in every dish. ## References and further reading - [Tandy TRS-80 Model 100 Computer](https://www.massmadesoul.com/features/trs80) on MassMadeSoul - A [wrist-mounted keyboard](https://adamleblanc.page/portfolio/schist01/) by Adam LeBlanc - An AI-inspired ["blursed" keyboard](https://www.reddit.com/r/MechanicalKeyboards/comments/1j12gow/the_grail_ai_inspired_design/) by Tschibo00 ∎