RAMDAC.TXT

RAMDACs

AcuMos:
ADAC1        15/16/24 bit.

Analog Devices:
ADV471       6bit DAC       15 overlay registers
ADV475       6bit DAC       15 overlay registers
ADV476       6bit DAC
ADV477       8bit DAC       15 overlay registers
ADV478       6/8bit DAC     15 overlay registers

ATI:
ATI68830     15/16/24bit    Up to 80 MHz    !
ATI68860     15/16/24bit    ???
ATI68875     15/16/24bit    Up to 135 MHz   ! Used in ATI Graphics Ultra + and 
                            Pro.  Same as TI34075 ??

AT&T:
ATT20c490    15/16/24 bit.  6/8 bit DAC.
ATT20c491    15/16/24 bit.  6/8 bit DAC w/gamma correction
ATT20c492    15/16/18 bit   6bit DACs. w/gamma correction
ATT20c493    15/16/18 bit   6bit DACs
ATT20c497    24bit          ?

Avance Logic:
ALG1101      16-bit.        Appears to be different from the other HiColor
                            DACs.

Avasem:
AV3676       6bit DAC

Brooktree:
Bt476        6bit DAC.
Bt478        6/8bit DAC.
Bt481
Bt482
Bt484        15/16/24bit    6/8bit DAC. Has hardware cursor.
Bt485        15/16/24bit    6/8bit DAC. Has hardware cursor.

Cirrus Logic
CL-GD5200    15/16/24 bit   Same as Acumos ADAC1 

Diamond:
SS2410       15/24 bit.     

Inmos:
IMSG171
IMSG176      6bit DAC
IMSG178

MUSIC:
MU9C1710     8 bit ??
MU9C4870     15/16 bit      Similar to Sierra "Mark 3".
MU9C4910     15/16/24bit

OAK:
OTI66        6bit DAC
OTI66HC      15/16bit       Similar to Sierra "Mark 3"

Samsung:
KDA476       6bit DAC

Sierra  "Mark1":       Only works if the VGA controller can send a byte on
                       both the rising AND falling edge of the dot clock.
SC11481      15-bit.        6-bit DAC.   Overlay.
SC11486      15-bit.        6-bit DAC.
SC11488      15 bit.        6/8 bit DAC. Overlay.

Sierra  "Mark2":
SC11482      15-bit.        6-bit DAC.   Overlay.
SC11483      15-bit.        6-bit DAC.
SC11484      15-bit.        6/8 bit DAC. Overlay.

Sierra  "Mark3":
SC11485      15/16 bit.     6-bit DAC.   Overlay.
SC11487      15/16 bit.     6-bit DAC. 
SC11489      15/16 bit.     6/8 bit DAC. Overlay.

SC15025      15/16/24 bit.
SC15026      15/16/24 bit.

UMC:
UM70c178     15/16 bit	      Similar to Sierra "Mark 3"


15-bit modes have 5 bits of each basic color:
bit  0- 4 blue.
     5- 9 green.
    10-14 red.
The pixel is stored in two bytes in Intel style (little endian).

16-bit modes have 5 bits of red and blue, and 6 bits of green:
bits 0- 4  blue.
     5-10  green.
    11-15  red.
The pixel is stored in two bytes in Intel style (little endian).

24-bit modes have 8 bits of each basic color:
bits 0- 7  blue.
     8-15  green
    16=23  red.
The pixel is stored in three bytes in Intel style (little endian).



The DACs are addressed on port 3C6h-3C9h. Advanced DACs have 1 or 2 extra
address lines (RS2 and RS3). These may be controlled from high address bits
(A10-A15) or from registers.
In the following +A is used if RS2 is set, +B is used if RS3 is set and +C if both RS2 and RS3 are set.



HiColor DACs:     (Sierra SC1148x, MUSIC MU9C4870, OAK OTI66HC, UMC UM70C178)

3C6h+A  (R/W):  Command Register
bit   5  (not SC11481/6/8)
         If set two pixel clocks are used to latch the two bytes
         needed for each pixel. Low byte is latched first.
         If clear the low byte is latched on the rising edge of the
         pixel clock and the high byte is latched on the falling edge.
         Only some VGA chips (ET4000 and C&T655x0) can handle this.
      6  (SC11485/7/9, OTI66HC, UM70C178) Set in 16bit (64k) modes (Only valid
           if bit 7 set). On the SC11482/3/4 this bit is read/writable, but
           has no function. On the SC11481/6/8 this bit does not exist.
      7  Set in HiColor (32k/64k) modes, clear in palette modes.
Note:  This register can also be accessed at 3C6h by reading 3C6h four times,
       then all accesses to 3C6h will go the this register until one of the
       registers 3C7h, 3C8h or 3C9h is accessed.

3C7h+A  (R/W):  Overlay RAM Read Address              (SC11481/2/4/5/8/9 only)
bit 0-3  Read index for the Overlay registers.

3C8h+A  (R/W):  Overlay RAM Write Address             (SC11481/2/4/5/8/9 only)
bit 0-3  Write index for the Overlay registers.

3C9h+A  (R/W):  Overlay RAM                           (SC11481/2/4/5/8/9 only)
bit 0-5  Data port for the overlay registers. Works like the PEL data register
         (3C9h) except that the overlay registers are accessed and the Overlay
         Address registers are used for indexes.
Note: on the SC11484/8/9 the Color Look-up Table and the overlay registers are
      24bits wide (rather than 18bits) if the 8/6 pin is high. 



Sierra SC15025/6 Truecolor DACs:

3C6h+A  (R/W):  Command Register
bit 5-7  Mode:  0: Normal, 3: 24bit, 4,5: 15bit, 6,7: 16bit
      4  If set 3C7h is the index port and 3C8h the data port for an extra
         register set:
           index   8h:   DAC width. 00h: 6bit, 01h: 8bit
                   9h:   53h
                   Ah:   00h ??
                   Bh:   DAC Speed. ACh: 135MHz, B1h: 80NHz
                Ch-Fh:   FFh ??
                  10h:   00h ??
Note:  This register can also be accessed at 3C6h by reading 3C6h four times,
       then all accesses to 3C6h will go the this register until one of the
       registers 3C7h, 3C8h or 3C9h is accessed.



AT&T 20c49x Truecolor DACs:

3C6h+A  (R/W):  Command Register
bit   1  (not 492,493) In mode 0 this bit when set selects 8bit DACs, when
         clear 6bit DACs.
    5-7  Mode:  0: Palette, 5: 15bit (32k), 6: 16bit (64k), 7: 24bit (16m)
Note:  This register can also be accessed at 3C6h by reading 3C6h four times,
       then all accesses to 3C6h will go the this register until one of the
       registers 3C7h, 3C8h or 3C9h is accessed.



BrookTree Bt484, Bt485 Truecolor DACs:

3C6h+A  (R/W):  Command Reg 0
bit    1  Set if DAC and palette registers are 8bit DACs, clear if 6bit.
       7  If clear the Status register is present at 3C&h+A, if set 3C8h
          determines which register is present at 3C6h+A:
            00h    Status Register
            01h    Command Register 3
3C6h+B is the Command Register 3, if clear the Status Register
         

3C7h+A  (R/W):  Cursor Read Address
bit 0-7  The PEL data register (0..255) to be read from 3C9h.
Note: After reading the 3 bytes at 3C9h this register will increment,
      pointing to the next data register.

3C8h+A  (R/W):  Cursor Write Address
bit 0-7  The PEL data register (0..255) to be written to 3C9h.
Note: After writing the 3 bytes at 3C9h this register will increment, pointing
      to the next data register.

3C9h+A  (R/W):  Cursor Data
bit 0-5  Color value
Note:  Each read or write of this register will cycle through first the
       registers for Red, Blue and Green, then increment the appropriate
       address register.
Note: the registers 3C7h-3C9h (+A) works like the normal 3C7h-3C9h registers,
      except that a separate set of palette registers (16 overlay registers ?)
      are being accessed.
      Index 00h  Overscan color
            01h  Cursor Background
            02h  Cursor Foreground

3C6h+B  (R/W):  Status Reg
Note: The two registers at 3C6h+B are selected by bit 7 of 3C6h+A.

3C6h+B  (R/W):  Command Reg 3
Bit  0-1  Bits 8-9 of the Palette Write Address (3C8h)
       2  Set if using 64x64 cursor, clear if 32x32 cursor.
       3  Enable Clock Doubler if set ?
Note: The two registers at 3C6h+B are selected by bit 7 of 3C6h+A.

3C7h+B  (R/W):  Cursor Ram Data
bit  0-7  Data port for the Hardware Cursor Map.
          There are 2 128byte (32x32bit) maps. The map at offset 0 is the
          cursor image and the one at 80h is the cursor shape.
          To update the cursor map, write the start address to 3C8h and start
          writing to this register. The index will increment for each byte.

3C8h+B  (R/W):  Command Reg 1
bit  0-7  Mode: 10h: 24bit, 30h: 15bit, 38h: 16bit, 40h: 8bit palette,
           60h: 4bit palette

3C9h+B  (R/W):  Command Reg 2
bit  0-1  Cursor mode. 2 for Windows, 3 for X11, 0 for off ??
       3  Set in interlaced modes ?
     2-7  Always 8 ??

3C6h+C  W(R/W):  Hardware Cursor X-position
bit 0-1  The X-position of the rightmost pixel of the hardware cursor

3C8h+C  W(R/W):  Hardware Cursor Y-position
bit 0-11  The Y-position of the lower scanline of the hardware cursor




Forcing HiColor DACs into command mode:

procedure dactocomm;   {switches DAC to command register}
var x:word;
begin
  x:=inp($3C8);    {clear old state}
  x:=inp($3C6);
  x:=inp($3C6);
  x:=inp($3C6);    {Read $3C6 4 times.}
  x:=inp($3C6);
end;

Now reads and writes to $3C6 will access the command register.
Any access to $3C7-$3C9 will switch back to the PEL mask register.


Forcing HiColor DACs into normal mode:

procedure dactopel;  {switches DAC back to normal mode}
var x:word;
begin
  x:=inp($3C8);
end;



function testdac:string;
var
  x,y,z,v,oldcommreg,oldpelreg:word;

type
  pel=record
        index,red,green,blue:byte;
      end;

procedure readpelreg(index:word;var p:pel);
begin
  p.index:=index;
  disable;
  outp($3C7,index);
  p.red  :=inp($3C9);
  p.blue :=inp($3C9);
  p.green:=inp($3C9);
  enable;
end;

procedure writepelreg(var p:pel);
begin
  disable;
  outp($3C8,p.index);
  outp($3C9,p.red);
  outp($3C9,p.blue);
  outp($3C9,p.green);
  enable;
end;

function setcomm(cmd:word):word;
begin
  dac2comm;
  outp($3c6,cmd);
  dac2comm;
  setcomm:=inp($3c6);
end;

procedure waitforretrace;
begin
  repeat until (inp(CRTC+6) and 8)=0;
  repeat until (inp(CRTC+6) and 8)>0;    {Wait until we're in retrace}
end;

function dacis8bit:boolean;
var
  pel2,x,v:word;
  pel1:pel;
begin
  pel2:=inp($3C8);
  readpelreg(255,pel1);
  v:=pel1.red;
  pel1.red:=255;
  writepelreg(pel1);
  readpelreg(255,pel1);
  x:=pel1.red;
  pel1.red:=v;
  writepelreg(pel1);
  outp($3C8,pel2);
  dacis8bit:=(x=255);
end;

function testdacbit(bit:word):boolean;
begin
  dac2pel;
  outp($3C6,oldpel and (bit xor $FF));
  dac2comm;
  disable;
  outp($3C6,oldcomm or bit);
  v:=inp($3C6);
  outp($3C6,v and (bit xor $FF));
  enable;
  testdacbit:=(v and bit)<>0;
end;

begin

  setDAC(_dac8,'Normal');
  dac2comm;
  oldcomm:=inp($3C6);
  dactopel;
  oldpel:=inp($3c6);

  dac2comm;
  outp($3c6,0);
  dac8:=dacis8bit;
  dac2pel;

  notcomm:=oldcomm xor 255;
  outp($3c6,notcomm);
  dac2comm;
  v:=inp($3c6);
  if v<>notcomm then
    if (setcomm($E0) and $e0)<>$e0 then
    begin           {Bits 5-7 of command register NOT writable.}
      dac2pel;
      x:=inp($3C6);
      repeat
        y:=x;         {wait for the same value twice}
        x:=inp($3C6);
      until (x=y);
      z:=x;
      dac2comm;
      if daccomm<>$8E then
      begin                 {If command register=$8e, we've got an SS24}
        y:=8;
        repeat
          x:=inp($3C6);
          dec(y);
        until (x=$8E) or (y=0);
      end
      else x:=daccomm;
      if x=$8e then setDAC(_dacss24,'SS24')
               else setDAC(_dac15,'Sierra SC11486');
      dac2pel;
    end
    else begin
      if (setcomm($60) and $E0)=0 then
      begin
        if (setcomm(2) and 2)>0 then setDAC(_dacatt,'ATT 20c490')
                                else setDAC(_dacatt,'ATT 20c490');
      end
      else begin
        x:=setcomm(oldcomm);
        if inp($3c6)=notcomm then
        begin
          if setcomm($FF)<>$ff then setDAC(_dacadac1,'Acumos ADAC1')
          else begin
            dac8now:=dacis8bit;
            dac2comm;
            outp($3C6,(oldcomm or 2) and $FE);
            dac8now:=dacis8bit;
            if dac8now then
              if dacis8bit then setDAC(_dacatt,'ATT 20c491')
                           else setDAC(_dacCL24,'Cirrus 24bit DAC')
            else setDAC(_dacatt,'ATT 20c492');
          end;
        end
        else begin
          if trigdac=notcomm then setDAC(_dacCL24,'Cirrus 24bit DAC')
          else begin
            dac2pel;
            outp($3c6,$FF);
            case trigdac of
              $44:setDAC(_dacmus,'MUSIC ??');
              $82:setDAC(_dacmus,'MUSIC MU9C4910');
              $8e:setDAC(_dacss24,'Diamond SS2410');
            else
              if testdacbit($10) then setDAC(_dacsc24,'Sierra 16m')
              else if testdacbit(4) then setDAC(_dacUnk9,'Unknown DAC #9')
                                else setDAC(_dac16,'Sierra 32k/64k');
            end;
          end;
        end;
      end;
    end;

    dac2comm;
    outp($3c6,oldcomm);
  end;
  dac2pel;
  outp($3c6,oldpel);

  if (dactype=_dac8) and (DAC_RS2<>0) and (DAC_RS3<>0) then
  begin
    oldpel :=inp($3C6);
    oldcomm:=inp($3C6+DAC_RS2);
    outp($3C6+DAC_RS2,oldpel xor $FF);
    if (inp($3C6)=oldpel) and (inp($3C6+DAC_RS2)=(oldpel xor $FF)) then
      SetDAC(_dacBt484,'Brooktree Bt484');

    outp($3C6+DAC_RS2,oldcomm);
    outp($3C6,oldpel);
  end;



  if dactype=_dac8 then
  begin
    WaitforRetrace;
    outp($3C8,222);
    outp($3C9,$43);
    outp($3C9,$45);
    outp($3C9,$47);    {Write 'CEGEDSUN' + mode to DAC index 222}
    outp($3C8,222);
    outp($3C9,$45);
    outp($3C9,$44);
    outp($3C9,$53);
    outp($3C8,222);
    outp($3C9,$55);
    outp($3C9,$4E);
    outp($3C9,13);     {Should be in CEG mode now}
    outp($3C6,255);
    x:=(inp($3c6) shr 4) and 7;
    if x<7 then
    begin
      setDAC(_dacCEG,'Edsun CEG rev. '+chr(x+48));
      WaitforRetrace;
      outp($3C8,223);
      outp($3C9,0);    {Back in normal dac mode}
    end;
  end;
end;


This ID's all known DAC types, except:
 - Sierra "mark2" and "Mark3" are all ID'd as Mark 3.

 - Avance Logic ALG1101 DAC can not be ID'd.

 - TI 34075, ATI 68830, 68860 and 68875 can not be ID'd

 - The Edsun CEG test has not been verified.