New SID ADSR Info!

Well, I wrote up a doc about new information found that sheds light on how the SID performs the ADSR prescaling. This prescaler is the 15 bit counter that divides the clock pulses coming in which then clock the envelope counter up/down.

* * * *

New SID info!
————-
08/02/2008
Kevin Horton
with help from:
Jonathan Gevaryahu AKA Lord Nightmare

New information about the SID ADSR circuit’s prescaler has been found by inspecting the SID’s die shots. Without further ado, here it is.

SID ADSR Prescaler
——————

Upon investigation, the SID uses a 15 bit LFSR for its prescaler, and NOT a counter. Resid and probably all other SID emulators handle this using a regular counter. The die on the SID, however, shows an odd little table for the ADSR prescale values. This table is reproduced below (LordNightmare entered it, thanks)

This is the small table as on the die. The bit polarities are unknown, as are the bit orders. All we know is the left 15 bits are the LFSR compare values, and the right 4 bits are the SID ADSR prescale values. This is the raw table as seen on the die shot:

100011111111010 0001
001101101010111 0000
111111111110001 1001
010110111001000 1000
010101010001100 0101
101110000001000 0100
111111001111101 1101
111111011110001 1100
111100110011111 0011
111000100110010 0010
110000111111111 1011
111011011110011 1010
100111111111111 0111
101110111011111 0110
111111110000000 1111
101101111011011 1110

After finagling around with some QBASIC code, I generated an exact match to this table. Here are the 16 values, in order. (It’s the same table as above, I just rearranged them in the proper order)

0123 are the 4 ADSR bits, and they are backwards and inverted. The 15 LFSR match bits are inverted also.

LSB -> MSB 0123
——————–
111111110000000 1111
100111111111111 0111
110000111111111 1011
111100110011111 0011
111111001111101 1101
010101010001100 0101
111111111110001 1001
100011111111010 0001
101101111011011 1110
101110111011111 0110
111011011110011 1010
111000100110010 0010
111111011110001 1100
101110000001000 0100
010110111001000 1000
001101101010111 0000

Aaand, here is my table, fixed up and in order. All the values turned out to be N-1, where N is the number of cycles it takes. i.e. for entry 0 which takes 9 cycles, the counter will expire after 8, but then it takes 1 cycle to reload it, which equals 9 total. The code example below implements this properly.

# comp value (hex, binary)
————————
0: 7F00 111111100000000
1: 0006 000000000000110
2: 003C 000000000111100
3: 0330 000001100110000
4: 20C0 010000011000000
5: 6755 110011101010101
6: 3800 011100000000000
7: 500E 101000000001110
8: 1212 001001000010010
9: 0222 000001000100010
A: 1848 001100001001000
B: 59B8 101100110111000
C: 3840 011100001000000
D: 77E2 111011111100010
E: 7625 111011000100101
F: 0A93 000101010010011

This pseudocode will implement the SID counter exactly as it works on the real chip.

adsrtable = [
0x7F00,
0x0006,
0x003C,
0x0330,
0x20C0,
0x6755,
0x3800,
0x500E,
0x1212,
0x0222,
0x1848,
0x59B8,
0x3840,
0x77E2,
0x7625,
0x0A93
];

feedback = (LFSR >> 14) ^ (LFSR >> 13); // perform XOR on last 2 bits
if (LFSR == adsrtable[rate]) // check to see if LFSR matches table value
{
LFSR = 0x7fff; // reset LFSR
// perform your envelope functions here
}
else
{
LFSR = (LFSR << 1) | feedback; // it wasn't a match, clock the LFSR once
}

4 thoughts on “New SID ADSR Info!”

  1. Nice work on the ADSR. Can you add a few details on how the LFSR is initialized (starting value)? I assume that the LUT value is loaded into the reg whenever the ADSR control reg is written? Also, how is the exponential decay envelope implemented? Any ideas?

Comments are closed.