This message from an unknown caller has sat on our landline answering machine since 2020 or 2021. No idea who or what sent it. All I know is it came in just before noon on a Tuesday morning. The entirely synthesized voice makes me think it’s a junk call, but there’s no scam attached. Just this message, slightly eerie, quite inexplicable.
Category: goatee-stroking musing, or something
-
The Quite Rubbish Clock, mk.2
this is bad and I should feel bad In early 2013, I must’ve been left unsupervised for too long since I made The Quite Rubbish Clock:
It still isn’t human readable … Written in (Owen Wilson voice) kind of an obsolete vernacular and running on hardware that’s now best described as “quaint”, it was still absurdly popular at the time. Raspberry Pis were still pretty new, and people were looking for different things to do with them.
I happened across the JASchilz/uQR: QR Code Generator for MicroPython the other day, and remembered I had some tiny OLED screens that were about the same resolution as the old Nokia I’d used in 2013. I wondered: could I …?

OLED Shield on a LOLIN S2 Mini: very smol indeed The board is a LOLIN S2 Mini with a OLED 0.66 Inch Shield on top, all running MicroPython. One limitation I found in the MicroPython QR library was that it was very picky about input formats, so it only displays the time as HHMMSS with no separators.
Source, of course:
# -*- coding: utf-8 -*- # yes, the Quite Rubbish Clock rides again ... # scruss, 2022-06-30 # MicroPython on Lolin S2 Mini with 64 x 48 OLED display # uses uQR from https://github.com/JASchilz/uQR # - which has problems detecting times with colons from machine import Pin, I2C, RTC import s2mini # on Lolin ESP32-S2 Mini import ssd1306 from uQR import QRCode WIDTH = 64 # screen size HEIGHT = 48 SIZE = 8 # text size r = RTC() # set up and clear screen i2c = I2C(0, scl=Pin(s2mini.I2C_SCL), sda=Pin(s2mini.I2C_SDA)) oled = ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c) oled.fill(0) def snazz(): marquee = [ " **", " **", " **", " **", " **", "********", " ******", " ****", " **", " quite", "rubbish", " clock", " mk.2", "<scruss>", " >2022<" ] for s in marquee: oled.scroll(0, -SIZE) # scroll up one text line oled.fill_rect(0, HEIGHT-SIZE, WIDTH, SIZE, 0) # blank last line oled.text("%-8s" % s, 0, HEIGHT-SIZE) # write text oled.show() time.sleep(0.25) time.sleep(5) oled.fill(1) oled.show() snazz() # tedious crowd-pleasing intro qr = QRCode() while True: qr.add_data("%02d%02d%02d" % r.datetime()[4:7]) qr.border = 1 # default border too big to fit small screen m = qr.get_matrix() oled.fill(1) for y in range(len(m)): for x in range(len(m[0])): # plot a double-sized QR code, centred, inverted oled.fill_rect(9 + 2*x, 1 + 2*y, 2, 2, not m[y][x]) oled.show() time.sleep(0.05) qr.clear()If your output is glitchy, you might need to put the following in boot.py:
import machine machine.freq(240000000)
This increases the ESP32-S2’s frequency from 160 to 240 MHz.
Update: there’s a fork of uQR that provides better character support, particularly those required for sending Wi-Fi Network config.
-
Hydraulic Tiles

recreated from the Threlkeld Granite Co Ltd’s Album: Ornamental Granitic Tiles (1898), sheet 8 The Internet Archive has Threlkeld Granite Co Ltd’s Album of ornamental granitic tiles online, and I’m really digging the patterns of the hydraulic tiles they made. I’ve recreated some of their patterns in InkScape, and made this small demo by tiling bitmapped renderings.
-
Adding RGB LEDs to an illuminated arcade button
Somewhat painterly view of the button doing its thing. The weird clunking sound is my camera’s continuous focus. For a clearer but more flickery view, see here Following on from a customer query at Elmwood Electronics, I can confirm that one can install install addressable RGB LEDs/NeoPixels inside one of these large buttons. It’s not the easiest build, so whether one should attempt this is another matter entirely.
You’ll need:
- Large Arcade Button with LED – 60 mm White (tall version) – this is larger and more domed than the flat-top one that Adafruit sells
- RGB LEDs – I used a generic 8 LED ring, but anything not too tall and under 45 mm in diameter should fit. Either a 7 X WS2812 5050 RGB LED Ring or Adafruit’s NeoPixel Ring – 12 x WS2812 5050 RGB LED with Integrated Drivers could also work
- Thin (and I mean thin: I used 28 AWG) Silicone Cover Stranded-Core Wire in several colours. You’ll want to cut this quite long at first, as you have to ease it through some tiny holes in the button assembly. If you solder connectors on the end, you won’t be able to disassemble or install the button without cutting them off. Do I speak from experience here? You betcha!
- The usual soldering/hot gluing/bending/prying/grabbing/cutting tools you already know and love. In addition, you might consider a non-marring spudger and a pair of small(ish) arterial forceps (aka hemostats, aka Kelly forceps, aka fishing hook removal pliers)
I’m not going to cover soldering the wires to the LED PCB in any depth here. You’ll need three wires: 5 V power, Ground and Data. Even though the LEDs I used need 5 V power, they are quite happy with 3.3 V logic on the data line. They need more than 3.3 V power to light, though.

The button in two pieces, as you might expect to receive it 
Main parts of the button top, once you’ve removed the lock ring 
First step is to ease the spring out without bending it too much or breaking the retainer tabs 
I used small forceps to ease the spring out. Once you get it started, it unscrews easily from behind the retainers 
Now the spring is out the way, you can squeeze in the actuator tabs and push them down the shaft to liberate the button top 
The button top disassembled 
Carefully lever off the clear top with a blunt tool like a spudger. Now would have been a great time to clean dust and other wee bits off your workspace, as they’ll surely end up inside the button, looking nasty 
The button top opened up. The cavity is about 45 mm in diameter and only a few millimetres deep 
Removing the LED holder from the microswitch is done by levering open (gently) the plastic tab that clamps the holder onto the switch. 
LED holder and microswitch separated. For normal button operation, the contacts NO and COM become connected when the button is pressed. The spade contacts on the LED holder look like they should come out, and they will (soon) 
Pull the LED out from the holder, and you’ll see the metal clips that held it in place. These clips have to come out: I found the pushing them in slightly while pulling down on the spade connector eased them out eventually 
LED ring hot glued into place. Make sure that the wires are properly secured, as you don’t want to take this apart again 
Fit the clear button top back inside the base, feeding the wires through the shaft. Fitting the return spring back in is a bit more chaotic than getting it out. I ended up jamming it in with forceps, and it seemed to sort out okay despite that 
The really fiddly bit: feeding the wires through the tiny gaps where the LED holder clips/contacts used to be. Even using thin (28 AWG) silicone covered wire, all three wires couldn’t fit down one side. Make sure the wires are pulled gently through, and aren’t snagged anywhere 
Finished! Make sure that the switch actuates properly by lining up the LED holder in the bayonets inside the shaft. Of course, you’ll have wanted to install the button in your project before doing this assembly, as you’ll have to feed those pesky wires back through again if you haven’t … -
you can colour this in if you want to

Jali pattern, as noted from the sleeve of Garifulla Kurmangaliyev’s recording of Asylzhan (Kazakhstan, 1958) in “Excavated Shellac: An Alternate History of the World’s Music” notes, p.173 PDF, too, if you like such things: record_label_jali.pdf. Made with OpenSCAD.
-
More Magic Designer Nonsense

This is what I simulated earlier – except drawn on a real Magic Designer. Something’s off with what I modelled … 
All of these are drawn with the Magic Designer angle set to 57, which puts the crank discs exactly in phase. The blue circle in the middle is an exactly image of a crank disc, if perhaps a very dull plot. -
Slightly imperfect Hoot-Nanny/Magic Designer simulation

I even emulated the locating notches at the edge of the paper … Simulated (and not quite right yet) output from a “HOOT-NANNY” or Magic Designer, a proto-Spirograph toy that drew six-sided curves on round paper sheets. It was made by Howard B. Jones and Co. of Chicago, IL and first sold in 1929. The company’s better known for producing Jones Plugs and Sockets, sometimes known as Cinch-Jones connectors. The “HOOT-NANNY” name was dropped when production moved to the Northern Signal Company of Saukville, WI.
My eBay-acquired Magic Designer is quite beaten up, and doesn’t always produce accurate results. Here’s how one should look, from the instruction pamphlet:

I can’t shake the feeling this was originally something like an artillery ranging tool or suchlike As far as I’ve been able to work out, the parameters of the machine are:
- central turntable is 6″ in diameter, with 192 gear teeth around the edge;
- (paper diameter is 5¾”);
- each crank disc is 1″ diameter (32 teeth), with the crank pin at ⅜” radius;
- the handle can only be turned clockwise. Consequently, the turntable can only turn anticlockwise;
- fixed pins at 90° and 180° are 6½” apart;
- distance between handle centre and fixed crank centre is 5″ on a 7″ PCD. Handle is therefore at ~225.585° and fixed crank at ~134.415°
- the shift lever has a 10-70° scale, which corresponds to moving the upper crank disc between 30-90° of arc from the lower (fixed) crank disc;
- the pencil arms have 18 holes labelled A to R, at ¼” spacing from 5¾ to 1½”. The perpendicular distance from the pivot holes to the pencil is 5/16″. This small offset makes very little difference to the overall arm length.
If we model the toy with a fixed turntable:
- the crank pins describe epitrochoids around the edge of the paper;
- the pencil point traces the intersection of two circles of radius the lengths of the pencil arms, each centred on a crank pin.
Here’s a very simple model in Python that emits a hard-coded (but editable) pattern in HP-GL: Slightly imperfect Python simulation of the “HOOT-NANNY” (or Magic Designer) drawing toy (static local copy: hootnanny.zip). It doesn’t do anything with the fixed circle studs (yet)
-
I spent all of yesterday calculating circular key grids …

a green thing … only to realize I don’t really like circular key grids.
-

Autumn in Canada: PicoMite version
So I ported autumn in canada from OpenProcessing to PicoMite BASIC on the Raspberry Pi Pico:

no leaves 
a couple of leaves 
more leaves 
plenty of leaves 
far too many leaves The biggest thing that tripped me up was that PicoMite BASIC starts arrays at 0. OPTION BASE 1 fixes that oversight. It would have been nice to have OpenProcessing’s HSV colour space, and an editor that could handle lines longer than 80 characters that didn’t threaten to bomb out if you hit the End key, but it’ll serve.
Source below:
' autumn in canada ' scruss, 2021-11 ' a take on my https://openprocessing.org/sketch/995420 for picomite OPTION base 1 RANDOMIZE TIMER ' *** initialize polar coords of leaf polygon and colour array DIM leaf_rad(24), leaf_ang(24), px%(24), py%(24) FOR i=1 TO 24 READ leaf_rad(i) NEXT i FOR i=1 TO 24 READ x leaf_ang(i)=RAD(x) NEXT i DIM integer c%(8) FOR i=1 TO 8 READ r%, g%, b% c%(i)=RGB(r%,g%,b%) NEXT i ' *** set up some limits min_scale%=INT(MIN(MM.HRES, MM.VRES)/8) max_scale%=INT(MIN(MM.HRES, MM.VRES)/6) min_angle=-30 max_angle=30 min_x%=min_scale% min_y%=min_x% max_x%=MM.HRES - min_x% max_y%=MM.VRES - min_y% CLS TEXT MM.HRES/2, INT(MM.VRES/3), "autumn in canada", "CM" TEXT MM.HRES/2, INT(MM.VRES/2), "scruss, 2021-11", "CM" TEXT MM.HRES/2, INT(2*MM.VRES/3), "just watch ...", "CM" kt%=0 DO cx% = min_x% + INT(RND * (max_x% - min_x%)) cy% = min_y% + INT(RND * (max_y% - min_y%)) angle = min_angle + RND * (max_angle - min_angle) sc% = min_scale% + INT(RND * (max_scale% - min_scale%)) col% = 1 + INT(RND * 7) leaf cx%, cy%, sc%, angle, c%(7), c%(col%) kt% = kt% + 1 LOOP UNTIL kt% >= 1024 END SUB leaf x%, y%, scale%, angle, outline%, fill% FOR i=1 TO 24 px%(i) = INT(x% + scale% * leaf_rad(i) * COS(RAD(angle)+leaf_ang(i))) py%(i) = INT(y% - scale% * leaf_rad(i) * SIN(RAD(angle)+leaf_ang(i))) NEXT i POLYGON 24, px%(), py%(), outline%, fill% END SUB ' radii DATA 0.536, 0.744, 0.608, 0.850, 0.719 DATA 0.836, 0.565, 0.589, 0.211, 0.660, 0.515 DATA 0.801, 0.515, 0.660, 0.211, 0.589, 0.565 DATA 0.836, 0.719, 0.850, 0.608, 0.744, 0.536, 1.000 ' angles DATA 270.000, 307.249, 312.110, 353.267, 356.540 DATA 16.530, 18.774, 33.215, 3.497, 60.659, 72.514 DATA 90.000, 107.486, 119.341, 176.503, 146.785, 161.226 DATA 163.470, 183.460, 186.733, 227.890, 232.751, 270.000, 270.000 ' leaf colours DATA 255,0,0, 255,36,0, 255,72,0, 255,109,0 DATA 255,145,0, 255,182,0, 255,218,0, 255,255,0You could probably use AUTOSAVE and paste the text into the PicoMite REPL. I used an ILI9341 SPI TFT LCD Touch Panel with my Raspberry Pi Pico along with some rather messy breadboard wiring.
Fun fact: the maple leaf polygon points are derived from the official definition of the flag of Canada.
-
p-touch Pico pin labels

Pico pin labels: not bad for a first try This worked better than I expected. The tricky parts are trimming the edges and getting it them straight.
Here’s the image to print on your label maker:

print on 12.7 mm tape -
Modding an Adafruit PIR for 3.3 volts

slightly dodgy soldering of a grey jumper wire to the Vout pin of the PIR’s voltage regulator Consider the Adafruit PIR (motion) sensor (aka PIR Motion Sensor, if you’re in Canada). Simple, reliable device, but only runs from a 5 V supply. Yes, there are smaller PIRs that run off 3.3 V, but if this is what you have, you need to do some soldering. Annoyingly, the sensor on the board is a 3.3 V part, but the carrier was designed in Olden Tymes when King 5 V ruled.
You can try powering it from 3.3 V, but it’ll go all off on its own randomly as its own power supply won’t be supplying enough voltage. There are a couple of sites on how to modify these PIRs that either describe old kit you can’t get any more, or do it completely wrongly. Just one post on the Adafruit support forum gets it right.
One way of doing this is to provide 3.3 V directly to the output pin of the voltage regulator, and ignore the 5 V power line entirely. The regulator’s a SOT89-3 part that looks a bit like this:

wee leggy thing In the photo above, it’s flipped over. Whichever way it’s oriented, we want to put power directly into the Vout pin. There may be easier points to solder this to than a tiny surface mount pin (almost definitely one of the capacitors) but this has held for me.
How to use it in MicroPython? Like the TTP223 capacitive touch sensors I looked at before, a PIR gives a simple off/on output, so you can use something like this:
from machine import Pin from time import sleep_ms pir = Pin(21, Pin.IN) while True: print("[", pir.value(), "]") sleep_ms(1000)value() will return 1 if there’s movement, 0 if not. There are trigger time and sensitivity potentiometers to fiddle with on the board if you need to tweak the output.

Thonny plotter output showing a couple of movement detections. High output (on my device) stays up for about 4 seconds, so you can be pretty leisurely about polling PIRs Just remember: don’t connect the 5 V power line if you make this mod. I’m not responsible for any smoke emitted if you do — but I can always sell you a replacement …
-
Lentil Soup
Ingredients
- 6 cups vegetable stock (or 3 veggie stock cubes + 6 cups water)
- 3-4 medium onions, chopped roughly
- 4-6 medium carrots; half chopped roughly, half grated
- 2 cups red split lentils
- 4-6 tbsp olive oil
- 2 tbsp baking soda (for soaking lentils)
Optional ingredients
- 1 tbsp prepared Dijon mustard
- 1 tbsp sweet paprika
Lentil Preparation
- Rinse and drain lentils at least three times: they should no longer clump, and rinse water should not be very cloudy
- Soak lentils in water with baking soda for at least an hour, occasionally stirring gently
- Rinse lentils and soak for at least an hour in clean water; drain.
Method
- Bring stock to a boil in a large pot. Add grated/chopped carrots and half the olive oil
- Fry onions in the rest of the olive oil until translucent, optionally with paprika
- Add fried onions to soup pot. Stir in Dijon mustard, if desired
- Cover and allow to low boil for 5-10 minutes
- Stir in drained lentils, and bring to a robust simmer
- Cover and simmer for 15 minutes.
- Serve and season to taste.
Notes
- This is based on my parents’ various lentil soup recipes from Scotland. They might use a ham or lamb-bone based stock
- Until recently, I’d been overcooking the lentils. Red split lentils are quite delicate, and soaking and lightly simmering gives a pleasing result
- The soaking in baking soda stage helps to de-gas the lentils
-
Snowy, after Paul Carter

non-artist’s impression of Snowy
(source SVG: white cat walking by papapishu on OpenClipArt)I’m remembering the time that Paul coloured a perfect square with a highlighter on their white family cat, Snowy. She had a pink side for weeks.
-
Raspberry Pi Pico with TTP223 Touch Sensor
This is almost too trivial to write up, as the TTP223 does exactly what you’d expect it to do with no other components.

TTP223 sensor board connected to GP22 / physical pin 29 Breakout boards for the TTP223 capacitive touch sensor come in a whole variety of sizes. The ones I got from Simcoe DIY are much smaller, have a different connection order, and don’t have an indicator LED. What they all give you, though, is a single touch/proximity switch for about $1.50
Trivial code to light the Raspberry Pi Pico’s LED when a touch event is detected looks like this:
import machine touch = machine.Pin(22, machine.Pin.IN) led = machine.Pin(25, machine.Pin.OUT) while True: led.value(touch.value())For the default configuration, the sensor’s output goes high while a touch is detected, then goes low. This might not be the ideal configuration for you, so these sensor boards have a couple of solder links you can modify:
- Active Low — sometimes you want a switch to indicate a touch with a low / 0 V signal. On the boards I have, the A link controls that: put a blob of solder across it to reverse the switch’s sense.
- Toggle — if you want the output to stay latched at one level until you touch it again, a blob of solder across the T link will do that. Unlike a mechanical switch, this won’t stay latched after a power cycle, though.
And that’s all it does. Sometimes it’s nice to have a sensor that does exactly one thing perfectly well.
- Active Low — sometimes you want a switch to indicate a touch with a low / 0 V signal. On the boards I have, the A link controls that: put a blob of solder across it to reverse the switch’s sense.
-
as I lait me down to sleep
found on a walk this morning This would be inexplicable outside Canada.
-
Niche Knowledge: Z80 parallel port SD card on Zeta2

Mini PPISD board: a slow SD card mass-storage system for 8-bit computers Almost no-one will need this knowledge, but I might need to remember it. In order to add Mini PPISD support to a RomWBW 3.01-supported system, you need to create a file called something like Source/HBIOS/Config/ZETA2_ppisd.asm (for yes, I’m using a Zeta SBC V2) containing:
#include "cfg_zeta2.asm" UARTCFG .SET UARTCFG | SER_RTS CRTACT .SET TRUE PPIDEENABLE .SET FALSE SDENABLE .SET TRUE PPPENABLE .SET FALSE PPISD .EQU TRUE
Running make from the top-level directory should create a ROM image called Binary/ZETA2_ppisd.rom for you to write to flash. Since my floppy drive isn’t feeling too happy, I had to resort to buying a TL866II Plus programmer to write the chip.
And it worked!
RomWBW HBIOS v3.0.1, 2021-03-12 ZETA V2 Z80 @ 8.000MHz 0 MEM W/S, 1 I/O W/S, INT MODE 2 512KB ROM, 512KB RAM CTC: MODE=Z2 IO=0x20 UART0: IO=0x68 16550A MODE=38400,8,N,1 DSRTC: MODE=STD IO=0x70 Sun 2021-03-14 17:47:13 CHARGE=OFF MD: UNITS=2 ROMDISK=384KB RAMDISK=384KB FD: IO=0x30 UNITS=2 SD: MODE=PPI IO=0x60 DEVICES=1 SD0: SDSC NAME=SD BLOCKS=0x003C7800 SIZE=1935MB Unit Device Type Capacity/Mode ---------- ---------- ---------------- -------------------- Char 0 UART0: RS-232 38400,8,N,1 Disk 0 MD1: RAM Disk 384KB,LBA Disk 1 MD0: ROM Disk 384KB,LBA Disk 2 FD0: Floppy Disk 3.5",DS/HD,CHS Disk 3 FD1: Floppy Disk 3.5",DS/HD,CHS Disk 4 SD0: SD Card 1935MB,LBA ZETA V2 Boot Loader ROM: (M)onitor (C)P/M (Z)-System (F)orth (B)ASIC (T)-BASIC (P)LAY (U)SER ROM Disk: (0)MD1 (1)MD0 (2)FD0 (3)FD1 (4)SD0 Boot Selection?
I was pleasantly surprised how easy it is to use a TL866 programmer under Linux. minipro does all the work, though. To write and verify the whole 512K Flash ROM, it’s:
minipro -p SST39SF040 -w ZETA2_ppisd.rom
The programmer supports over 16000 devices, of which around 10000 are variants (form factor, programming voltage, speed, OTP, etc). It’ll also verify over 100 different 74-series logic chips. It’s not a super cheap device (mine was a little over $80, from Simcoe Diy) but it does a lot for that price.
Next stop: try rebuilding BBC BASIC with RomWBW’s timer support included ..
-
ZX81 40th Anniversary
So the Z80-powered doorstop that got so many people started with computers was launched 40 years ago.
My story is that we never had one: we had three, but only for a week each. It’s not that they failed, either. My dad, who ran the computer bureau at King George V Docks for the Clyde Port Authority, was Glasgow’s representative on the European Association for Data Processing in Ports (EVHA). The group was looking at ways for automating ship identification, efficient berthing and documentation handling.
All the ports had data centres, but most of the mainframe time was for predefined tasks such as dock-worker payroll. There wasn’t the budget for computer time to try some of the experimental projects that may have helped with port automation.
Several EVHA members were trying home computers unofficially, but many of them were too expensive to come in under expense account rules. These “big†micros required a business case and purchase order to buy. The ZX81, limited as it was, did fit in the expense budget and – equally importantly – fitted into my dad’s suitcase as he made his monthly trips to Europe.
The week before my dad was scheduled to leave, he’d buy a ZX81. Of course, it needed “testingâ€, something me and my brother were only too happy to do. At the end of the week, it would get packed up and on its way to Europe.
I’m not sure if the clandestine micros were ever actually used for controlling ship traffic (you get considerably fewer than three lives manoeuvring an LNG tanker), but more likely in simulation. I understand that the ZX81 was able to simulate the traffic management for the entire Port of Rotterdam for a while, at least until its RAM pack wobbled.
reposted from ZX81 40th Anniversary – Histories – Retro Computing




