To configure the SID chip and keep it isolated from errant automation, I chose to use MIDI SysEx messages. These special MIDI events allow us to send arbitrary amounts of "proprietary" data from device to device without having to worry about interfering with others on the chain. To do things properly, you're supposed to register for and use an actual MIDI vendor ID, but since chances are highly unlikely this will ever be produced and used in the wild, I opted to use the experimental vendor code 0x7D.
This page, as you can guess, exists simply to describe the various system exclusive messages SIDI understands and what it expects as parameters. If you're not going to be talking to this thing directly on the wire yourself, you can safely skip this section.
Note that the byte lengths given below are for the messages themselves and do not include the required wrapper. For example, "Set Volume" is advertised as a 1 byte message, but you'd actually need to send 4.
SIDI also expects all SysEx messages to be properly formatted, eg:
0xF0 0x7D [msg1] ... [msgN] 0xF7
Voice Off (0x00)
This message is used to turn off either a specific voice or all 3 voices. It expects one byte which is treated as number between 0 and 4, where 0-2 represent an individual channel and 4 represents all voices.
Set ADSR (0x01)
The ADSR message consists of 5 bytes: The first is treated as a number between 0 and 3 which indicate the channel whose envelope we wish to adjust.
The next 4 bytes contain the 4-bit ADSR values to be output directly to the chip. It's probably best to read the data sheet to find out the lengths of time these numbers represent.
Pulse Width (0x02)
This 4-byte long message is used to set the pulse width (or duty cycle) of a channel's oscillator. The first byte, as usual, is treated as a number between 0 and 2 which represents the channel to modify.
The next 3 bytes of the message contain the high four, middle four, and low four bytes (respectively) of the 12-bit width.
Set Shape (0x03)
As each of the SID's voices allows for 4 different waveforms which can be (allegedly) XOR'd together, this is treated as a 4-bit bitmask on the high 4 bits of the byte (but this really should change):
- Bit 5: Triangle (16)
- Bit 6: Sawtooth (32)
- Bit 7: Square (64)
- Bit 8: Noise (128)
The first byte contains the channel to modify (0-2) and the next byte is a 4-bit mask indicating the new shape exactly as it would be passed to the SID's data lines.
Note that, due to laziness, I used the actual bit values we'll be sending to the SID, so this will need to change for life on a real MIDI chain as setting the noise pattern can inadvertently trigger a spurious End of SysEx event.
Set Test (0x04)
This will set the specified channel's test bit. You can toggle this bit on and off to perform a "soft reset" of a specific oscillator if you've done something it doesn't like, ie. an ill-conceived XOR involving the Noise wave shape.
This message is 2 bytes, the first indicates the channel, the second whether to clear or set (0 or 1) the test bit.
Set Sync (0x05)
Sets or clears the synchronized bit for the specified channel. The SID handles synchronization as follows:
- Oscillator 1 will be synchronized with Oscillator 3
- Oscillator 2 will be synchronized with Oscillator 1
- Oscillator 3 will be synchronized with Oscillator 2
Note that for sync to work, the oscillator with which you're synchronizing cannot be set to a frequency of 0 (obviously).
This message is 2 bytes, the first a number between 0-2 indicating the channel and the second either 0 or 1, where 1 will activate sync and 0 will turn it off.
Ring Modulation (0x06)
Activates or deactivates ring modulation with another oscillator, the result of which will be available on the specified channel's triangle wave. You will also need to toggle the second oscillator's gate or sync bit otherwise modulation will not occur. The SID's modulation works as follows:
- Voice 1 is modulated with Voice 3
- Voice 2 is modulated with Voice 1
- Voice 3 is modulated with Voice 2
As expected, this is a 2-byte message, the first indicates the channel and the second the ring modulation state (0 or 1).
Gates (ie. turns on) the specified oscillator. Due to the way SIDI works, the frequency from a Note On event isn't lost when the Note Off event is received. To use the gate bit manually, you will need to send back-to-back Note On and Note Off events before triggering the gate.
This is a 2-byte message, the first byte indicates the channel and the second the gate state (0 or 1).
Adjusts the volume for the SID chip as a whole. If using a 6581, this could also theoretically be used for playing back "digis", which were 4-bit audio sampled audio playable by exploiting an audible "click" whenever the chip's volume is changed.
This message is one byte indicating the requested volume as a number between 0 (off) and 15 (full).
Activates or deactivates arpeggio mode on the specified channel. While in arpeggio mode, multiple Note On events will result in a trill of up to 5 roughly 32nd notes instead of the current note being overwritten with the new one.
This is a two byte message, the first a number between 0 and 2 indicating the channel, the second 0 or 1 to (respectively) deactivate or activate arpeggio mode.
Arpeggio mode as it exists now was a very quickly hacked together affair and is currently broken. Making use of it will result in either a single note being played or the Arduino freezing.