Grid-based Tiling Window Management, Mark III, aka QuickGridZones
With a laptop and a 4K monitor, I wind up with a large number of windows scattered across my screens. The general disarray of scattered and randomly offset windows drives me nuts.
I've done some work to address this problem before (here and here), which I had been referring to as "quicktile". But that's what KDE called its implementation that allowed snapping the window to either half of the screen, or to some quarter. On Windows, there's a Power Tool called "Fancy Zones" that also has a few similarities. In an effort to disambiguate what I've built, I've renamed my approach to "Quick Grid Zones".
Since the last post on this, I've done some cleanup of the logic and also ported it to work on Windows.
This isn't a cross-platform implementation, but rather three implementations with some structural similarities, implemented on top of platform-specific tools.
- Linux KDE - KDE global shortcuts that call a Python script using xdotool, wmctrl, and xprop
- Mac OS - a lua script for Hammerspoon
- Windows - an AutoHotKey2 script
Simple demo of running this on KDE:
Grab the local tarball for this release, or check out the QuickGridZones project page.
LDraw Parts Library 2023-02 - Packaged for Linux
LDraw.org maintains a library of Lego part models upon which a number of related tools such as LeoCAD, LDView and LPub rely.
I packaged the 2023-02 parts library for Fedora 36 to install to /usr/share/ldraw; it should be straight-forward to adapt to other distributions.
The *.noarch.rpm files are the ones to install, and the .src.rpm contains everything so it can be rebuilt for another rpm-based distribution.
ldraw_parts-202302-ec1.fc36.src.rpm
ldraw_parts-202302-ec1.fc36.noarch.rpm
ldraw_parts-creativecommons-202302-ec1.fc36.noarch.rpm
ldraw_parts-models-202302-ec1.fc36.noarch.rpm
See also LDrawPartsLibrary.
LeoCAD 23.03 - Packaged for Linux
LeoCAD is a CAD application for building digital models with Lego-compatible parts drawn from the LDraw parts library.
I packaged (as an rpm) the 23.03 release of LeoCAD for Fedora 36. This package requires the LDraw parts library package.
Install the binary rpm. The source rpm contains the files to allow you to rebuild the packge for another distribution.
Fixing a "blank screen" after a failed flash of an Ender-3 Pro
The Problem:
I have a Creality Ender-3 Pro that came with a 32bit 4.2.2 motherboard. The firmware on these boards can be updated by booting from a correctly prepared uSD card containing compatible firmware. (This is done by "the bootloader", which I will refer to as the "second-stage bootloader" hereafter because there is a first-stage bootloader in ROM which jumps to the second-stage bootloader at the beginning of flash, which in turn handles any firmware upgrade and then jumps to the firmware later in the flash. Being pedantically precise is important when dealing with machines at this low level.)
But if something goes wrong with a firmware upgrade, you can be faced with a device that shows only a blank screen, and very little to go on when trying to diagnose why it won't flash a correct firmware.
If the board does not attempt to flash, and boots into the existing working firmware, you should see the splash screen about 2 seconds after power is applied. If the board successfully flashes the updated firmware, you should see a blank screen for about 15 seconds, and then the splash screen of the new firmware. If the board does not attempt to flash and the existing firmware is broken, you will see a blank screen forever. If the board flashes a broken firmware, you will also see a blank screen forever.
I'm not the only one who ran into this issue, and I found a lot of advice online regarding this, but the second-stage bootloader on this board seems to be rather finicky, which led to people drawing apparently erroneous conclusions about what they did to fix their machines.
The documentation mentions that you should use a uSD card 8GB or smaller. But I have found that a properly-prepared 512MB uSD card does not work either. So it appears that there is also a lower bound to the uSD card size somewhere between 8GB and 512MB.
It is commonly believed that the firmware file must be named firmware<number>.bin, where <number> is a number different from what was previously flashed. I found that the requirement is that the file be named <something>.bin, where <something> is different from what was previously flashed. For example, I was able flash the firmware from a file named Ender-3 Pro- Marlin2.0.1 - V1.0.1 - TMC2225 - English.bin
And to be explicit, it only tracks the most recently flashed filename. If you have two uSD cards, one with firmware1.bin and the other with firmware2.bin, you can boot from them alternately, and successfully re-flash each time.
I have also seen people suggest using an 8.3 filename (limiting oneself to 8 character filename and 3 character bin extension). However, the firmware correctly identified that Ender-3 Pro- Marlin2.0.1 - V1.0.1 - TMC2225 - English2.bin differed from Ender-3 Pro- Marlin2.0.1 - V1.0.1 - TMC2225 - English.bin and flashed the image.
I found people talking about using a freshly formatted or brand new uSD card, and frequently people blamed cheap uSD cards as being faulty, including the uSD card that came with the printer. It appears to me that this is misattributing to the uSD hardware what is really a problem with the second-stage bootloader. Starting with an 8GB uSD card containing a correct firmware file, I would wind up with a blank screen. Taking that same 8GB uSD card, wiping the entirety of it with zeros, creating a vfat filesystem on it, copying that same firmware file to it, and flashing from that would reliably succeed. Writing an image of the previous filesystem to the uSD card would reliably recreate the blank screen problem. So the problem was clearly with the data, not with the hardware.
It appears that the history of the filesystem must play a role in the blank screen problem. The original uSD card, with all files deleted, and a correct firmware file copied to it, was causing the blank screen problem. I must conclude that the second-stage bootloader is looking at deleted file entries, or the data blocks for the firmware file were fragmented in some way that confused it, or... something. My attempts to produce a filesystem from scratch that would exhibit this behavior were not successful.
I've seen instructions about having to create a partition on the uSD card at exactly the right place. However, I found I could reliably flash the board with no partitioning of the device.
Solution
At this point, I can reliably flash the board with this process:
Fully wipe and format the device by running these commands as root:
dd if=/dev/zero bs=1G of=/dev/mmcblk0 mkfs -t vfat /dev/mmcblk0 sync
Caution: Ensure that you use the correct device name for your system (/dev/mmcblk0 was the device on my machine); using the wrong device could wipe and reformat your entire laptop.
When using the SD card slot on my laptop, the sync was superfluous, but when using a USB uSD card adapter, it would aggressively cache the writes and the bulk of the time was spent waiting on the sync. (That process takes about 12 minutes on my machine with the uSD card that shipped with the printer.)
Mount the device, then copy the firmware file to it as firmware1.bin, unmount the device. Insert it into the board, power on, and wait for it to flash and boot into the new firmware. If it does not attempt to flash, rename the firmware file and try again.
Caveats:
While debugging this, I attempted many scenarios with various parts of the system disconnected, such as all the motors, switches, sensors, and heaters. In order to get a handle on the variables, I did my testing to draw the conclusions in this article with the motherboard connected to the LCD screen, all other components disconnected, and powered by the micro USB port. I did verify that I was able to flash the firmware with the LCD screen disconnected; i.e., with the only connection to the board being the micro USB cable to power it. I did not see any indication that the board behaved differently with everything disconnected vs with everything properly connected and installed in the printer. But with the number of flaky oddities I saw in working through this, such context is important to capture.
I have upgraded my Ender-3 Pro with the 4.2.7 silent motherboard, and ran into the same blank screen problem when trying to flash it to support the CR Touch. I was able to recover it using the same techniques above.
Sabaton Index updates; new song "The First Soldier"
Sabaton released a new song this month about Albert Severin Roche titled The First Soldier along with a few history videos on Sarajevo, The Battles of Doiran, and the Dreadnought. They've also filled in some lyric videos for past songs.
I've updated SabatonIndex with the discography and videos they've released of late.
LDraw Parts Library 2022-06 - Packaged for Linux
LDraw.org maintains a library of Lego part models upon which a number of related tools such as LeoCAD, LDView and LPub rely.
I packaged the 2022-06 parts library for Fedora 36 to install to /usr/share/ldraw; it should be straight-forward to adapt to other distributions.
The *.noarch.rpm files are the ones to install, and the .src.rpm contains everything so it can be rebuilt for another rpm-based distribution.
ldraw_parts-202206-ec1.fc36.src.rpm
ldraw_parts-202206-ec1.fc36.noarch.rpm
ldraw_parts-creativecommons-202206-ec1.fc36.noarch.rpm
ldraw_parts-models-202206-ec1.fc36.noarch.rpm
Cooling fan Lego assembly
I have a SeaWit 4-port HDMI KVM switch (similar to this one on Amazon) that I suspected might be overheating. I didn't have any fans blowing across it, and it was in a stack of other electronic devices, so I'm not sure blame attaches. Still, I needed some way to get some air across it.
For this type of application, I prefer a blower fan design rather than a propeller fan.
I found a four-pack of small, inexpensive USB-powered 5V 50mm x 50mm x 15mm fans on Amazon.
The KVM switch wasn't designed with fan mounting holes or anything, so I needed some sort of frame assembly to hold them. So of course I reached for my mechanical engineering rapid prototyping kit, better known as my Lego collection.
The mounting holes of those are a snug fit for a Technic pin with friction, which can then be used to mount them to a Lego assembly.
The distance between the mounting holes does not quite align with Lego dimensions, but a Technic beam provides the needed adjustment.
I developed two assembly types. If the fan is positioned to draw air from below (so that small random objects don't fall into the fan blades), then the fan can be above (type 1) or below (type 2) the supporting structure.
Type 1: Fan above supporting structure
model file and building instructions
The physical build, with the fan installed:
Type 2: Fan below supporting structure
model file and building instructions
The physical build, with the fan installed:
Note that for this build, I adjusted the width of the structure by tacking on a couple extra bricks to the top. It's a trivial change, but made for a better fit around the KVM switch's feet.
This seems to work for cooling the KVM switch, and while two fans is probably overkill, having two assembly types does give me some flexibility.
Sabaton Index updates; new song "Father"
Sabaton released a new song last month related to World War One titled Father and a related history video about Fritz Haber.
I've updated SabatonIndex with the discography and videos they've released of late.
LDraw Parts Library 2022-05 - Packaged for Linux
LDraw.org maintains a library of Lego part models upon which a number of related tools such as LeoCAD, LDView and LPub rely.
I packaged the 2022-05 parts library for Fedora 34 to install to /usr/share/ldraw; it should be straight-forward to adapt to other distributions.
The *.noarch.rpm files are the ones to install, and the .src.rpm contains everything so it can be rebuilt for another rpm-based distribution.
ldraw_parts-202205-ec1.fc34.src.rpm
ldraw_parts-202205-ec1.fc34.noarch.rpm
ldraw_parts-creativecommons-202205-ec1.fc34.noarch.rpm
ldraw_parts-models-202205-ec1.fc34.noarch.rpm
Grid-based Tiling Window Management, Mark II
A few years ago, I implemented a grid-based tiling window management tool for Linux/KDE that drastically improved my ability to utilize screen realestate on a 4K monitor.
The basic idea is that a 4K screen is divided into 16 cells in a 4x4 grid, and a Full HD screen is divided into 4 cells in a 2x2 grid. Windows can be snapped (Meta-Enter) to the nearest rectangle that aligns with that grid, whether that rectangle is 1 cell by 1 cell, or if it is 2 cells by 3 cells, etc. They can be moved around the grid with the keyboard (Meta-Up, Meta-Down, Meta-Left, Meta-Right). They can be grown by increments of the cell size in the four directions (Ctrl-Meta-Up, Ctrl-Meta-Down, Ctrl-Meta-Left, Ctrl-Meta-Right), and can be shrunk similarly (Shift-Meta-Up, Shift-Meta-Down, Shift-Meta-Left, Shift-Meta-Right).
While simple in concept, it dramatically improves the manageability of a large number of windows on multiple screens.
Since that first implementation, KDE or X11 introduced a change that broke some of the logic in the quicktile code for dealing with differences in behavior between different windows. All windows report location and size information for the part of the window inside the frame. When moving a window, some windows move the window inside the frame to the given coordinates (meaning that you set the window position to 100,100, and then query the location and it reports as 100,100). But other windows move the window _frame_ to the given coordinates (meaning that you set the window position to 100,100, and then query the location and it reports as 104,135). It used to be that we could differentiate those two types of windows because one type would show a client of N/A, and the other type would show a client of the hostname. But now, all windows show a client of the hostname, so I don't have a way to differentiate them.
Fortunately, all windows report their coordinates in the same way, so we can set the window's coordinates to the desired value, get the new coordinates, and if they aren't what were expected, adjust the coordinates we request by the error amount, and try again. That gets the window to the desired location reliably.
The downside is that you do see the window move to the wrong place and then shift to the right place. Fixing that would require finding some characteristic that can differentiate between the two types of windows. It does seem to be consistent in terms of what program the window is for, and might be a GTK vs QT difference or something. Alternatively, tracking the error correction required for each window could improve behavior by making a proactive adjustment after the first move of a window. But that requires maintaining state from one call of quicktile to the next, which would entail saving information to disk (and then managing the life-cycle of that data), or keeping it in memory using a daemon (and managing said daemon). For the moment, I don't see the benefit being worth that level of effort.
Here is the updated quicktile script.
To use the tool, you need to set up global keyboard shortcuts for the various quicktile subcommands. To make that easier, I created an importable quicktile shortcuts config file for KDE.
Of late I have also noticed that some windows may get rearranged when my laptop has the external monitor connected or disconnected. When that happens, I frequently wind up with a large number of windows with odd shapes and in odd locations. Clicking on each window, hitting Meta-Enter to snap it to the grid, and then moving it out of the way of the next window gets old very quickly. To more easily get back to some sane starting point, I added a quicktile snap all subcommand which will snap all windows on the current desktop to the grid. The shortcuts config file provided above ties that action to Ctrl-Meta-Enter.
This version works on Fedora 34; I have not tested on other distributions.