Simulating a slow phosphor CRT on Gameduino 3

Over on the Gameduino 3 forums, gregkovacs asked:

I'm working on a way to achieve the same "slowly fading" effect of a slow phosphor CRT as seen here.
https://vimeo.com/293844792
The example shows low-pass-filtered white noise from an avalanche-breakdown transistor for X- and Y-axes (truly random). If sampled at around 100 samples/second, the signal should be faithfully captured. However, the fading effect, which is very cool, takes place over many seconds, which seems to preclude storing that many points (maybe 10,000 x/y pairs) and fading them exponentially over maybe 10 seconds with a circular buffer approach.
That's certainly a nice effect, and since I had some code lying around that might help. I've spent an hour putting together something similar for the GD library.

I'm using a Gameduino 3 7" - which has a resolution of 800x480. To use it on a Gameduino 3 4.3" model you should adjust the coordinates for its 480x272 screen. I'm also assuming that there's plenty of host memory - this won't fit on an Arduino because it uses a whole 4K of RAM for the point buffer. This is running on a $2 STM32 "blue pill" using the (currently experimental) port of the GD2 library to the STM32.

The general approach is to draw a lot of points, one for each sample, and hope that they're dense enough to merge into a solid curve. The EVE GPU can draw about 2000 points, so here I'm running with 1024 points, which works nicely with the 100 points/second sampling rate and a ten second decay.

The idea is to match an analog phosphor screen, so it will look better if the point is drawn as a soft-edged glow. Here's a 32x32 "glow" bitmap I made about 20 years ago:


Drawing 1024 these in a line, in an appropriate greenish glow color produces this. It's important to set the blend mode to addition, so that the glows all accumulate. Once again this is what a physical phosphor screen does - its image is a simple summation of glows:

This image was deleted by MailChimp when they shut down TinyLetter.
This looks promising, but a little wide. Tweaking the glow bitmap's parameter to make it a little smaller gives something that looks much more like a scope trace. The other change is to steadily increase the brightness in the loop that draws the bitmaps. This duplicates the time fading effect: older points are fainter than newer ones. Because there are 1024 points, it makes sense to set the brightness every 4 points, so there are 256 brightness levels. This gives a nice smooth gradient:

This image was deleted by MailChimp when they shut down TinyLetter.
Of course I don't have an analog transistor to generate an interesting x,y trace. So instead I used another piece of old code to produce a random path. Plugging it in to update the array of 1024 vertices gives a path across the screen that's starting to look quite like a phosphor scope. You can see the faded "old" trace in the background, to the left.

This image was deleted by MailChimp when they shut down TinyLetter.
Looking at the original video, you can see that the current beam of the CRT is extremely bright. Drawing the most recent few points with a brighter, larger glow gives a striking effect that's somewhat similar. This glow is 64x64 pixels, and the most recent 4 points are being drawn this way:

This image was deleted by MailChimp when they shut down TinyLetter.
That's all it takes. There is a youtube video here with a short capture of the output.

https://youtu.be/IdYvdGQJloA

The code is here.