Updating Framework's QMK Firmware

New BIOS for Framework 16, brought also a problem. Every boot I got a message that my keyboard firmware is outdated. It was true, but also annoying warning as it paused the boot process. Normal person would just update keyboard but I had a few customizations and thus could not do the same.

What customizations? Well…

  • Entering QMK firmware by holding CapsLock (keyboard) or NumLock (numpad)
  • Key to mute microphone
  • Disabling airplane mode key
  • Reconfiguring numpad to allow volume and media controls
  • Using brightness as a NumLock signal
  • Simplifying background light setup

Could I live without those? Yes, but I still would prefer not to. So, I had to redo my changes on top of v0.3.1 which was simple enough as I just pretty much cherry-picked my changes directly. Maybe for the next version I also squash a few of them but I was lazy this time.

Short flash later and my numpad had a newer firmware with the same behavior. Happily I proceeded to flash the keyboard but in my excitement, I forgot to change my command line from framework/numpad to framework/ansi. Thus, I flashed my numpad firmware onto my keyboard. Annoying mistake but easily corrected by just reflashing the correct firmware on top of it. Or so I though.

My keyboard still didn’t work even after the correct firmware has been flashed. Some keys did produce something but it was never a correct letter. Did I brick my keyboard? Well, fortunately for me, with QMK answer is never yes.

QMK flashing doesn’t erase the full EEPROM when new version is loaded. So, if you end up corrupting the whole thing by flashing something very incompatible, you cannot just flash new firmware and be ok. What you need is to erase the old firmware all together. There are a few tools to do it, but I like this one.

Once EEPROM was erased, flashing my keyboard firmware worked like a charm.

Using ZFS in Docker

I have most of workloads on my server setup in Docker. It makes for self-documenting configuration, easier move to other machine, and less dependencies on the underlying OS. But one workload I kept on server itself - reporting.

The way my scripts were written, they required proper ZFS access. Now, I could adjust script to loopback via SSH to OS itself, but there was an easier way.

Docker allows for device exposing, and in the case of ZFS, all you need is to point container toward /dev/zfs:

    devices:
      - /dev/zfs:/dev/zfs

Now your scripts in container will have proper ZFS access.

Forcing a reboot

After messing with my remote server, there came a time for a reboot. Simple enough - but this time it ended in error.

Call to Reboot failed: Connection timed out

I’ve been using Linux servers for decades now and I was never faced with this issue. Fortunately, somebody at Unix StackExchange did.

Solution was to manually enter a few letters into /proc/sysrq-trigger, one letter at a time.

echo s > /proc/sysrq-trigger ; echo u > /proc/sysrq-trigger ; echo b > /proc/sysrq-trigger

This (attempts to) execute three distinct commands:

  • s: syncs all file systems
  • u: makes all file systems read-only
  • b: reboots the system in agressive manner.

If you are curious about what other things you can do, kernel.org has a nice documentation page.

Reconnecting HDMI

Illustration

Switching my media PC from Windows to Bazzite went awfully uneventful. No issues whatsoever. At least for a while.

My media computer is connected to TV courtesy of type-C HDMI output. And I verified heck out of it. Computer’s output worked flawlessly with TV.

However, once TV was off for a while, turning on TV would result in “No Signal” message. At first I though it was sleep, but no. Computer was still reachable via network and it would all start working after reboot. A lot of troubleshooting later and I found a pattern, courtesy of DP status:

cat /sys/class/drm/card1-DP-2/status

If I run it while TV was on, I would see connected status. If I turn TV off, I would still see connected status. But, once I turned TV back on (after some time has passed), status would change to disconnected. And nothing I’ve tried to do over network helped. Well, nothing but one thing.

If you ever used Ctrl+Alt+Fx keys, you saw virtual terminals in action. Most of the time we only do stuff on the first terminal, but other terminals are sometime handy too. Switching to other terminal would actually reset connection every time. And that is something you can do from the command line.

chvt 2
sleep 1
chvt 1

Figuring it out was the first part. While I now knew how to recover connection to my TV, having to do it every time via network was annoying. I wanted something automatic.

The first step was creating script in /usr/local/bin/dp-reconnect:

#!/bin/bash

function status() {
    for DP_PATH in /sys/class/drm/card1-DP-*; do
        DP_STATUS=$( cat "$DP_PATH/status" | grep '^connected$' | xargs )
        if [[ "$DP_STATUS" == "connected" ]]; then
            echo "Display $( basename "$DP_PATH" ) connected"
            exit 0
        fi
    done
}

status
echo "No connected displays"

chvt 2
sleep 1
chvt 1

status
exit 1

Next step is to create service definition at /etc/systemd/system/dp-reconnect.service:

[Unit]
Description=Switch terminal if no DP is connected

[Service]
Type=oneshot
ExecStart=/usr/local/bin/dp-reconnect

And lastly, we can create timer in /etc/systemd/system/dp-reconnect.timer:

[Unit]
Description=Switch terminal if no DP is connected

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=true
AccuracySec=1s

[Install]
WantedBy=timers.target

With all files in place, the only remaining task is to enable the timer.

sudo systemctl enable --now dp-reconnect.timer

With all in place, if display gets disconnected, script will reconnect it within a minute. Not perfect but lightweight enough not to be a serious hassle.

The 5-pin RS-232 Framework Expansion Card

My previous RS-232 Framework expansion card worked like a treat for 90% of use cases. Due to historical reason, most of RS-232 communication was limited in moder times to just TX and RX lines. But ocassionally one would also benefit of the hardware synchronization. And my expansion card had none.

Illustration

Once I decided onto hardware control, question was which one. Due to historical reason, there are two distinct ways you might employ hardware to control flow: RTS/CTS and DTR/DSR. Ideally I would have supported both but instead I opted to support only more common (and more modern) RTS/CTS. Why?

Well, the first reason is transciever. I love to use MAX232-style transcievers and they offer only 2-in and 2-out lines. Could I have changed which transciever to use? Most definitelly. There are different transciever that support full 4-in, 3-out signals needed for a full RS-232. However, MAX232 is well understood, has a bunch of “clones” that are equaly good, and it’s pretty much trouble-free. While back in days I ocassionally strayed into other RS-232 transcievers, I was almost always sorry later.

The second reason is the connector. Adding 2 extra lines would bring connector to 7 pins and that size would require moving LEDs from edge since I wouldn’t have enough PCB remaining. If we go further and add a CD line needed for full RS-232 (yes, I am ignoring Ringo as people often do), connector would even lose its symetry. Restricting oneself to 5-pin RS-232, is much more reasonable choice.

Illustration

With the new design sorted out, it was time to get PCB. And PCBWay didn’t disappoint. With framework expansion cards, the standard edge routing bit will be too large. I’ve had mixed luck with oother PCB suppliers but never with PCBWay. They always switch to a smaller edge routing bit and produce a perfect PCB. Not sure if it’s human checking that triggers it, or it’s good automation, or maybe they tend to use smaller bit than USA does by default. Whatever it is, they never messed up my board.

This time I also wanted to try their 3D printing service and they didn’t disappoint. Prints I received were perfect in all ways. If you ever printed Framework card case, you know that side rail features are easy to mangle without supports. Your printer really needs to be dialed in. With PCBWay all prints I receved had perfectly embossed text on the bottom and side rails that were perfectly sized and smooth.

Since I wanted to compare their print with what comes out from my printer, I opted for the basic PLA. That means you cannot expect print to be without visible lines. That’s just a nature for the process and if you mind them, resin prints will probably work better for you. But I can definitelly say that even this PLA print was better than what I produce.

Illustration

Now, the difficult question is whether it’s worth it. Prints that I got were cheap but definitelly not as cheap as printing at home. Depending on your printer, it might take a bit (or more) of effort to get results close to what PCBWay provides and that’s before even considering shipping or tariffs. But, for resin prints, my calculation slightly changes. PCBWay provides basic resin printing at lower cost than PLA. Combine that with a general “messiness” of resin printing and hardening and you have a reasonably priced alternative. Yes, shipping and tariffs still blow but for ocassional print you are better off than buying resin printer and all chemicals yourself. While I might not be the perfect fit for this service, I am glad it exists and I do plan to use it again in the future.

Here is where I would usually say that you can get card from my store but it was not meant to be. Even though this was a second PCB for this release (I forgot to select 0.8mm thickness the first time), I made a considerable blunder. I accidentally swapped CTS and RTS lines. Doh!

Mistake was trivial but not really easily fixable by a bodge wire. I am reasonably sure there are no other mistakes but I won’t know until I get new PCBs. Until then, this will be a Schrödinger’s project. Both completed and not, at the same time.