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

}