exSID USB is a MOS Technology SID hardware playback device that connects to modern computers via USB. The goal of this project is to enable accurate, true to the original hardware playback of SID music (such as what can be found in the High Voltage SID Collection) in a convenient, 21st-century compatible way: without a working C64. Needless to say, it sounds fantastic: it will exSID your expectations! :)
This project has been inspired by the original SIDBlaster/USB, which is no longer available.
I occasionally have some kits available for sale (without SID chips), drop me a line if interested :)
This project falls under a different licensing scheme than the rest of this website. Please read this section carefully.
- The hardware part (incl. firmware) of this project is licensed under a Creative Commons BY-NC-SA license (“NC” is for Non-Commercial).
- The software part (excl. firmware) is licensed under the GPLv2.
Note: I would like to emphasize that the CC BY-NC-SA specifically prohibits commercial use of the licensed material. Please get in touch if you need more information.
The information and methods described herein are provided “AS-IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. Use the concepts, examples and information at your own risk. There may be errors and inaccuracies, that could be damaging to your devices. Proceed with caution, and although it is highly unlikely that accidents will happen because of following advice or procedures described in this document, the author does not take any responsibility for any damage claimed to be caused by doing so.
My design goals are primarily focused on playback accuracy and ease of use:
- KISS design
- USB bus powered
- Must be able to playback digis (aka samples)
- Must support both 6581 and 8580 SID variants
- Must be 100% 8-bit architecture (because that’s the spirit :)
- Easy to program
Presently, the following features are implemented:
- Fully bus powered (no external power supply)
- Support of precomputed digis (typically at cycle-accurate timings)
- Near cycle-accurate playback:
- Minimum time between consecutive I/O: 10 cycles (10μs), cycle-accurate within that limitation
- Typical average jitter when playing digis: 0 cycle
- Support for 44.1kHz digis (such as “Musik Run/Stop”)
- Automatic switching between 6581 and 8580
- Limited support of SID read operations
- Fixed SID clock (1MHz)
The following features are being worked on for a more elaborate future design (the name is exSID+ and a working prototype is seeing slow but steady development!):
- Onboard stereo mixer
- Support for NTSC/PAL exact clocking (for exact original pitch and song pace)
- Tighter timings
- Upgradable via USB
- Support for both external and USB power
Finally, in the longer term I would like to enable support for read-based digis.
If you wonder how it sounds like, I think a few examples will be most convincing, so here they are:
- A classic tune featuring a prominent digi intro: Ghostbusters (on 6581)
- Another classic game tune played on the 8580: Monkey Island (on 8580)
- A tune that makes very heavy use of digis for the guitar riff: Skate or Die (on 6581)
- Finally an example of the stereo chorus described below, 8580 on the left channel and 6581 on the right: Thing on a Spring
All tunes are raw captures straight from the device, without any additional processing.
Here’s the schematic of the revision C design:
The design is fairly straightforward, and it is based on two key components: the FT232R USB UART IC, which handles the USB protocol and converts received data to RS232 serial protocol; and a PIC16F882 micro controller, which handles SID management. This PIC has plenty of I/Os, thus I didn’t find necessary to multiplex address and data lines. LED2 lights when data is being exchanged between the device and the host, and LED1 indicates the device is correctly powered (see below).
This schematic reflects one key constraint of the design: reduce as much as possible the current draw of the device. Since it must be bus-powered, USB specs state that it can only draw 500mA max (even though recent motherboards can deliver more). Some tradeoffs had thus to be made to ensure that this limit was respected.
The SID chips have special power requirements (by virtue of being old NMOS logic circuits), so they each have a dedicated power converter (V1 and V2) providing the required VDD voltage (+9V for 8580 and +12V for 6581). These converters are powered through a switched power line that only turns on after the FT232R has successfully completed USB handshake and requested the necessary current to operate the device (485mA). In fact, the USB specification forbids any device to draw more than 100mA until it has negotiated high power mode with the host controller. The FT232R controls Q1 via a soft-start circuit to trigger the secondary +5V rail after this negotiation has completed. Without it, the host controller would shut down the port because the initial current draw would be out of spec.
Note: the device may not operate on a bus-powered USB hub, since it might not be able to draw enough current: in that case, LED1 will not turn on. Besides, to avoid dropouts and additional noise, it’s highly recommended to plug the device directly into a free USB host port.
Likewise, the USB specification also limits inrush current on VBUS, which translates into a maximum capacitance of 10μF between VBUS and ground, hence the choice of value for C4.
The PIC’s /MCLR pin is wired via a pull-up resistor to the switched +5V power rail, so that the PIC only starts up after all voltages are present in the circuit. The large pull-up ensures compatibility with ICSP. This wiring has several advantages, including the ability to eventually interact with the PIC while the SIDs are powered down (by making RE3 an input); and also reduces the current flowing through Q1 and thus the voltage drop.
The audio output stage is a very simple follower transistor buffer stage that mimics the C64’s original output stage. The SID outputs a fairly hot signal (maxing at about half of the DC bias – see below – i.e. around 2-3VP-P) so it doesn’t really need further amplification. The input RC load is the exact same implementation as on the original C64. It filters out frequencies above about 16kHz (to reduce unwanted noise in the transistor), and that frequency is high above the SID’s maximum frequency. It’s a first-order filter anyway, so the roll-off will be gentle. The emitter follower stage buffers this signal to provide impedance isolation as well as increased protection (in particular against ESD) to the SID chips, while reducing the current flowing in the analog part of the chips (high input impedance). This reduces power dissipation at the chip level (heat). It also provides a low output impedance, which is desirable to drive line-level inputs. This stage also delivers enough current gain to be able to plug headphones directly into the output, even though that is not the intended use (current will be limited by the converters and this might result in distortion, and there will be a loss in the bottom-end of the output signal due to impedance mismatch). In case it isn’t obvious, this output stage shows only so much concern about linearity or noise floor: these are fairly irrelevant given the source we’re dealing with, the already ultra-noisy SID chip.
Typical 2N3904 have been chosen as they’re readily available and perform well in audio configurations. Biasing is simplified as the SID output signal already rides at a DC bias (4.5 to 6V) corresponding to half of VDD, so the transistor can operate in class-A, with a circa 5mA quiescent current (a good compromise for reduced power dissipation) set by the emitter resistor (R8/R10). Audio is AC-coupled to a stereo output jack (each SID on a separate channel) via a current limiter resistor (R11/R12). While not strictly necessary, that resistor helps preventing damage to the transistors or converters in case the output goes short-circuit (and also helps stability when driving capacitive loads, e.g. long cables). Finally, an intermediary header (OUT) allows for custom wiring if desired.
A fairly critical consideration for bus-powered USB devices is USB power usage. USB specifications stipulate that a USB port can deliver a maximum of 500mA at 5V, for a total of 2.5W of power. The device must fit this power envelope, and it turns out it is in fact quite below it. The following table gives ballpark figures sourced from datasheets when available and estimates or design-set values otherwise.
|Component||Current typ (mA)||Current max (mA)||Note|
|6581 Vdd||77||125||Accounting for TME0512 77% efficiency|
|8580 Vdd||60||95||Accounting for TME0509 76% efficiency|
|LEDs x2||5||6||For 2-2.5V LED drop|
|2N3904 x2||27||35||Quiescent current, TME efficiency accounted|
The above figures are resulting current draws on the +5V USB line. The totals assume both channels would operate at the same time, which is the worst-case scenario.
The alloted 485mA current envelope for device operation (as set in the FT232R configuration) should thus cover the worst case scenario. It doesn’t leave much for other devices in a bus-powered hub configuration, but such a setup is discouraged anyway.
As with all my designs, this one is very modular. If you don’t plan on ever using more than one particular SID, the other can go as well as its accompanying voltage converter and output buffer.
Conversely, it’s technically possible to implement a “chorused” stereo effect by using two identical SIDs (make sure the voltage converters are set accordingly) and modifying the software to enable dual playback. The feature is implemented in the PIC firmware and it enables both SIDs to play the same thing. Due to typical differences between two chips, this yields a natural and pleasing chorus. Of course it also works with two different SIDs (6581 and 8580) but since they don’t sound alike at all (the 8580 can’t really play digis for instance), it can be surprising on some tunes.
As mentioned, the design uses a PIC16F882 which is the adequate requirement to run the current firmware code with all features implemented. Pin-compatible PICs known to work include the 16F882, 16F883 and 16F886. The design can also operate with the cheaper, pin-compatible PIC16F72X devices 16F722, 16F723 and 16F726. With these models however, it is not possible to reach the maximum performance of the device: contrary to the 88X family which features a 16-bit baudrate generator and can achieve a 2Mbps RS232 asynchronous baudrate, the 72X family only has an 8-bit generator. This is why the firmware operates at a reduced 750kbps rate with these devices, and this in turn impacts the playback performance and quality: this mode also has a maximum 2-cycle resolution for timings, contrary to the cycle-accurate 2Mbps mode. Finaly, the design implements ICSP for easy hacking.
Note: compatibility with 72X family is only provided as proof of concept and should not be regarded as officially supported.
UPDATE: support for 16F72X devices has been dropped in exsid driver 1.5.
Here’s a compact two-sided through-hole layout that fits on 85 x 45 mm PCB.
The partlist is here.
Here’s a completed revision B PCB:
The assembly guide is here.
This layout is fairly straightforward. Routing has been done by hand, with a focus on compactness, simplicity and “user-friendliness” (as few SMDs as possible, easy to assemble by hand). It uses a ground plane for all the usual reasons (simplified routing, better shielding against noise and better coherence of the ground level across the whole PCB). The mini-USB connector is a through-hole model to ensure robustness, and the shield is connected to ground. Analog signals (audio) are mostly self-contained and as far away from potential “polluters” as possible.
The output jack, a through-hole Lumberg 1503-09 (1503-17 also works), is optional. A 3-pin header labelled OUT is provided on the board should you want to customize output wiring. Each SID is on either side of the header, with ground on the center pin.
Everything can be soldered by hand, but Q1, and even moreso the FT232RL (being a TSSOP device) are going to require some skill. There are a lot of tutorials out there, but here are good examples of two radically different methods:
With adequate gear, here’s a nice video of what one can do with practice (and a steady hand).
Note: I also highly recommend to put the PIC and both SIDs in sockets, for all the obvious reasons (not exposing them to soldering temperature or ESD, and easy replacement).
This design relies on a custom-designed firmware for the PIC. The firmware source is abundantly commented, but the general coding goals were as follows:
- Ensure correct timings for the SIDs
- Make the code as fast as possible (necessary to reduce jitter and sustain the data throughput)
- Fit the program on the smallest variant of the PIC family (so small memory footprint)
The code makes use of several programming tricks to implement these goals, which may make the code flow sometimes difficult to follow. The program is divided in several routines, starting with the __INIT one, which sets the hardware up at power-on time. This routine provides the 1MHz SID clock signal, and configures the USART interface for 2Mbps transfers based on the FT232RL-provided global clock at 24MHz. And yes, while spec’d at maximum 20MHz, the PIC has absolutely no problem coping with this 20% overclock ;). This is actually made possible by the fact that none of the analog functions nor the EEPROM are being used.
The program then calls the __INITTUNE routine to play a startup chime, confirming that the SIDs are operating properly.
After returning from there, the code goes on to reset the SIDs, and waits for incoming data. From that point on, only GOTOs are used and the code is written to ensure that every subroutine maintains SID clock alignment.
The program basically expects to receive bytes, corresponding to an address or data. The way addresses are handled probably requires some explanation: in order to simplify the address decoding logic and make the code faster, a branch table is used to process incoming addresses. Normal SID addresses are passed to their respective immediate data write or read routines. But since SID addresses are only 5-bit long, the 3 extra bits are also used to encode a time offset for the delayed routines, enabling much more accurate reads and writes and reducing jitter. Finally, interleaved with the SID address-space are a handful of IOCTL routines that perform various tasks (such as delays, chip selection, version information or reset).
This design enables very efficient access to the device and greatly simplifies both firmware code and computer-side software.
Considering the calculated power usage previously mentioned, the FT232R is programmed to request a fairly liberal 485mA.
The provided files can be programmed on all the supported PIC devices. A template to program the FT232R is also attached.
Current firmware version is 11.
A C library driver has been developed for controling the device. It provides basic routines for I/O operations, and enables accurate timings. This library supports both libFTDI, an open source library to talk to FTDI chips which supports a large variety of platforms, and FTDI’s official D2XX drivers.
The library supports Linux, OSX and Windows (via MinGW).
Note: best results are obtained using libftdi.
While written with cycle-accuracy in mind, this driver must cope with the limitations of USB. In order to avoid saturating the USB host controller and to achieve maximum throughput, I/Os are buffered. This is why read support is limited as it is technically impossible to perform a round-trip (read then write) in as little time as direct interfacing with the CPU allows a C64 to do.
Current driver version is 2.1, and is available on GitHub (kindly hosted within libsidplayfp):
The driver documentation is available here.
sidplayfp has native support for exSID since version 2.0, it is the preferred software to use with exSID.
Note: Due to the limitations of USB and the hardware, it is impossible to play back SID tunes making heavy use of reads (such as Reed’s Flamethrower).
Picture of a completed unit
With a custom-made clear acrylic case and retro 8-bit logo :)