SID 6581R3 ADSR tables, up close.

In the center of any SID emulation there is the bare waveform generation, and a very accurate explanation of how the this works internally has been published through an interview with its creator, which can be read here. Fascinating read for any geek head!

However some very important details are missing, including the exact maths behind the main ADSR clocking but also its pseudo exponential decay/release stages.

It was time to have a look at the SID's DIE itself!
This is exaclty what kevtris and Lord Nightmare have done here

The SID chip has two obvious ROM based lookup tables on the DIE,  for each voice. Here is the bigger one, as described in kevtris's blog entry:


I basically just cropped parts of the picture of the chip, which is available here, and placed the bit values on top of it.

However the blog post doesnt mention, nor explain the purpose of the second table, which I assumed was one of the "exp" tables, as mentionned in the Yannes Interview:

Yannes: "In order to more closely model the exponential decay of sounds, another look-up table on the output of the Envelope Generator would sequentially divide the clock to the Envelope Generator by two at specific counts in the Decay and Release cycles. This created a piece-wise linear approximation of an exponential. I was particularly happy how well this worked considering the simplicity of the circuitry.".

The SID patent's figure 10 mentions the following dividers are used: 30,16,4,2,1 . Hum not quite divide by two heh? 32,16,8,4,2,1 would have been more logical!

So lets try to decode the exact table on the DIE...

Well I didnt have a big clue myself, as reading bits of a DIE is all new to me, but after discussing with Lord Nightmare and kevtris, it appears this is also a LFSR counting trick, this time with a 5bit long LFSR and taps on bits 2 and 4:


Here is that table in plain ascii:
SSSSS  A B  A B  A B  A B  A B
00100  0 1  0 1  1 0  0 1  0 1    
00001  0 1  0 1  0 1  0 1  1 0    
01000  0 1  1 0  1 0  1 0  0 1    
00010  1 0  1 0  1 0  0 1  1 0    
10000  1 0  1 0  0 1  0 1  0 1    

Kevtris explained that the left hand part is a "Selector" of sorts, since there is only one bit active on each line/column. The second part seems to contain inverted pairs of bits..... hmm puzzling...

Using similar code to what they provided, this time for the second table, and only taking the 'B' bits as LSB:

const unsigned short exp_lfsr[5] = {
    0x1B, 0x0F, 0x11 , 0x08 ,0x1C
};

for (size_t i=0;i<5;i++){   
  unsigned int LFSR=0x1F;   
  size_t c=0;   
  while(1){     
    if (LFSR == exp_lfsr[i]){            
       exptable[i]= c;       
       break;     
     }     
     else{       
        c++;
        LFSR = ((LFSR << 1) | (((LFSR >> 2) 
          ^ (LFSR >> 4)) & 1)) & 0x1F;
     }
   }
}

the results in exptable is 8,30,4,16,2, (which mostly matches the numbers in SID patent, except for the missing 8... and the weird order.

Ok so we know that at some points in the decay of the envelope, the clock divider changes... what does that mean exaclty and what are those "points"????

Heres what we can try:

We know the SID chip has two readable registers which are tied to the 3rd voice: One for the 8bit ENV value ($D41C) and the other for the 8 most significant bits of the waveform generator (which is 12 bits internally) at $D41B

So by setting the 3rd SID Oscillator's release at longest rate ($F), and by hooking up a CIA Timer to callback at each $7a13 cycles (which comes from the phase2 counter lenght for release 'F' according to kevtris/LN), we can, in theory, get a synchronized sampling of the envelope and store the results for analysis. As im lasy and that seeing is believing, I just programmed to display the values on the screen while the note decays.

Here is a live capture of that code running on a BreadBox c64 stuffed with a 6581R4AR:



If you know your Screen Codes, you can see that the envelope goes from 255 to 0, and that some values start to repeat at certain points...

The chars to look for are:
"|": (93)  switches to 2  waits before a drop
"6": (54)  switches to 4  waits before a drop 
"Z": (26)  switches to 8  waits before a drop
"N": (14)  switches to 16 waits before a drop (Thanks Frank!)
"F": (06)  switches to 30 waits before a drop

So while I can now go on with my emu code, knowing what happens, I'm still clueless on WHERE/HOW this comparison happens on the DIE. So if you have a clue, or spot anything wrong in my logic, please add a comment!

Comments

  1. That sure was interesting! Thanks for posting, now I am off to read more of your blog.

    yerpa58

    ReplyDelete
  2. I've recently found out where the comparison
    is made on the die. Are you still interested
    in this information?

    ReplyDelete
  3. I've recently found out where the comparison
    is made on the die. Are you still interested
    in this information?

    ReplyDelete
  4. Okay... where can I mail a
    descriptive GIF and a small document to?

    ReplyDelete
  5. I found a small mistake:

    "|": (93) switches to 2 waits before a drop
    "6": (54) switches to 4 waits before a drop
    "Z": (26) switches to 8 waits before a drop
    "N": (14)!!!!!! switches to 16 waits....
    "F": (06) switches to 30 waits before a drop

    ReplyDelete
  6. Corrected 14 vs 16

    please try 'davidv' and plogue.com as domain for email+comments
    Thanks

    ReplyDelete
  7. Several complaints. :-) Article uses acronyms without defining them (ENV, LFSR, etc). Uses C code, which is absurd since all C64 documentation is done in Basic or Assembly or using labeled diagrams. The Yannes interview link can be found now via the Internet Archive.

    ReplyDelete

Post a Comment