webSID-Pi

In previous posts I had documented some “Raspberry Pi 4B” related ramblings and this post here may clarify why I was interested in that device in the first place.

It’s been some years that I’d created a C64/SID music emulator for the Web called webSID (see https://bitbucket.org/wothke/websid). I still have somewhat fond childhood memories of my respective 80ies home computer which had started my career in software engineering (particularly memories of its signature music creation capabilities).

If you have ever written any sort of music hardware emulation you are certainly well aware that there is absolutely no shortage of “fanboys” that know exactly what some original hardware sounded like and who are happy to tell you that your pretentious emulation sounds egregiously wrong. In the case of the SID sound chip, the manufacturer MOS had produced various models (6581 vs 8580) and revisions (of those models) that had different hardware designs (and production tolerances related differences) affecting the chip’s actual audio output. Consequently the opinions of “fanboys” here tend to be somewhat useless, since they may well be based on one particular chip revision.

Obviously the only authoritative reference is the use of the actual SID sound chips. One way to go about testing respective chips would be to use an old C64. However this approach has some obvious drawbacks: By today’s standards the respective hardware is an extremely slow piece of garbage and it takes forever to even load/run the minuscule programs. Respective 40 year old hardware components (power supply, CPU, PLA and VIC II chips) are prone to die and are more and more difficult to find replacements for. Different songs may require an NTSC or a PAL version C64 (affecting the used clock rate and the behavior of the VIC II chip). Different SID models require different hardware environments, e.g. different supply voltages (9V vs 12V) was well as different filter capacitors.

Given that my webSID emulation already covers all the required runtime environments I decided to ditch the respective non-SID legacy hardware and connect the SID chips directly to a “Raspberry Pi 4B” and drive it via the available GPIO pins.

The below image shows my respective prototype board. The design is actually fairly simple: The SID chip is dropped into the prototyping socket in the center. A boostconverter (red PCB) is used to create the 9V or 12V supply for the SID chip based on the Pi’s 5V. The filter capacitors suitable for the used SID model are plugged in (see green caps between SID and the boostconverter). (I had originally also used a hardwired 1 MHz crystal oscillator but later replaced it with the Pi’s built-in clock signal generator.)

The main problem with running a SID chip from a C64 emulation on a Raspberry PI is that the available operating system is not meant for realtime applications: By default various processes used by the OS are preemptively scheduled to run on the available CPU cores.

Ideally you would want to let the emulation step through the ~1Mhz clock cycles of the emulated C64 hardware one by one in realtime, and you’d have to somehow synchronize that processing with the actual processing speed of the Raspberry (though the overhead for synchronizing each 1MHz cycle would be excessive). The processing cost of different cycles also might vary, and though fast enough on average, sporadic peaks might potentially exceed the available time window for some of the cycles.

Fortunately for practical SID playback purposes the timing constraints can be somewhat relaxed: All of the SID’s timing is directly driven via the Pi’s hardware clock signal and when SID registers are updated respective player routines usually expect to make updates with 50Hz to maybe 200Hz frequency. Even if an update is slightly out of sync, it will usually not be noticeable here. The most timing critical interaction comes from songs that use the C64 CPU to trigger SID changes for the purpose of playing digi-samples. Respective samples may then be played (worst case) with a frequency of about 30kHz (meaning that updates should then ideally occur every 33 micros, i.e. there is some margin as compared to the ~1 micro clock timing).

I decided to go for a two-threaded buffered design: One CPU core is reserved for the emulation thread that generates a batch of SID updates (with respective target timestamps) for the next time window. And a second CPU core is dedicated to a playback thread that consumes the output of the emulation thread and that polls for the current time to perform the SID updates when the time is right.

As a first attempt I configured the program to run exclusively in user space and it actually ran good enough for regular SID songs. Unfortunately the preemtive multi-tasking used by the Linux OS causes timing glitches that are quite noticable in songs that use “digi-samples” tricks.

I tried to limit undesirable interference effects from other programs by isolating use of the relevant CPUs (see isolcpus, rcu_nocbs, rcu_nocb_poll and nohz_full) but unfortunately the remaining 100Hz “arch_timer” IRQs still seem to prevent a clean playback.

As a workaround I then created a kernel module for the playback thread and that version indeed plays nicely without any glitches. But eventhough the respective version may sometimes run fine for multiple minutes, there still seems to be some part of the kernel that sporadically crashes the system – probably due to the “playback” thread completely blocking “its” dedicated CPU core. The test results suggest that this problem might be fixed if the component that triggers the crash can be identified and disabled. Unfortunately I am not familiar with the respective Linux kernel implementation and I currently don’t feel like looking for that needle in the haystack. (Please let me know in case you have an idea how I might hack the kernel to work around the issue.)

Here the results created by the respective programs:

PS: More information on this project can be found here: https://bitbucket.org/wothke/websid/src/master/raspi/

Posted on April 22, 2021, in C, Chiptune, HW emulation, SID. Bookmark the permalink. Leave a comment.

Leave a comment