Outils pour utilisateurs

Outils du site


back2root:tutoriaux:vga-avance-dac-part-1

Ceci est une ancienne révision du document !


Le DAC

Le moniteur doit commander l'intensité des trois faisceaux d'électrons (rouge, vert, bleu) qui vont permettre l'affichage des différentes couleurs. Cette intensité est une valeur analogique qui n’est pas présente au cœur d’une carte VGA (qui traite les intensités de façon numérique).

Le DAC possède une palette qui, à un index de couleur (choisi parmi 256), associe les proportions des trois signaux de base rouge, vert et bleu. Ces proportions peuvent être modifiées par le programmeur pour chacune des 256 couleurs. Le DAC se charge alors de traduire les proportions associées à une couleur en signaux analogiques parfaitement compréhensibles par le moniteur.

La modification des valeurs de la table se fait de manière assez simple en spécifiant l’index de couleur a modifié sur le port 0x3C8 (PEL Address), et en injectant 3 octets (un pour chaque intensité) sur le port 0x3C9 (DAC), le DAC se chargeant de placer les valeurs dans les registres ad-hoc.

mov        al,colorID      ; choose color ID
mov        dx,0x3c8        ; DAC PEL address
out        dx,al                 
 
mov        dx,0x3c9        ; DAC
 
mov        al,db_Red   
out        dx,al           ; write Red level for colorID
 
mov        al,db_Green       
out        dx,al           ; write Green level for colorID
 
mov        al,db_Blue
out        dx,al           ; write Blue level for colorID

Raster

A quoi cela peut il servir ?

Et bien à créer un dégradé sur la couleur de fond par exemple, et ce dans n’importe quel mode « couleur » de la carte VGA ; meme en mode texte… ca peut servir par exemple pour “enrichir” un menu de configuration…

#include "dos.h"
#include "conio.h"
 
typedef unsigned char BYTE;
typedef unsigned int  WORD;
 
// copper_maxrow is a parameter to avoid copper/raster to turn forever
// copper_error must be set to 0 to run
 
int    copper_maxrow        = 400;
BYTE    copper_error        = 0;
 
// this constant define the raster precistion (for percentage calculation)
#define PRECIS                    8
 
/*
  Draw a raster with RGB(sr,sg,sb) -> RGB(dr,dg,db) in « count » lines
 
  0 mean 0, 255 mean 100 %
*/
 
void DrawRaster(BYTE st_red, BYTE st_green, BYTE st_blue, BYTE dt_red, BYTE dt_green, BYTE dt_blue, WORD count )
{
  int   step_percent;
  char  step_red, step_green, step_blue;
 
  // Since the VGA color range is only 6 bit, we divide by 4 the byte
  st_red      = st_red>>2;
  st_green    = st_green>>2;
  st_blue     = st_blue>>2;
 
  dt_red      = dt_red>>2;
  dt_green    = dt_green>>2;
  dt_blue     = dt_blue>>2;
 
        asm {
        xor   ah,ah                   // calculate Red Stepping
        mov   al,dt_red               // endcolor - startcolor
        mov   bl,st_red
        sub   al,bl
        mov   step_red,al            // red delta = endredcolorlevel - startredcolorlevel
 
        xor   ah,ah
        mov   al,dt_green             // calculate Green Stepping
        mov   bl,st_green
        sub   al,bl
        mov   step_green,al
 
        xor   ah,ah
        mov   al,dt_blue              // calculate Blue Stepping
        mov   bl,st_blue
        sub   al,bl
        mov   step_blue,al
        xor   cx,cx                   // cx = 0 (current line = 0)
 
        mov   dx,0x3DA }              // wait for stable know line count (0)
w1: asm {
        in    al,dx
        test  al,0x08                
        jne   w1 }
w2: asm {
        in    al,dx
        test  al,0x08
        je    w2 } 
 
start:asm {
        cli                           // protection overscan : Current line > max
        mov   bl,0x05                 // error 5 : overload
        cmp   cx,copper_maxrow        // line counter over max ?
        jae   eocl
 
        cmp   cx,count                // raster completed ?
        jae   clean_eocl
        inc   cx                      // current line ++
        mov   dx,0x3da }              // read input state   
in_retrace:asm    {   
        in    al,dx                   // test if we are redrawing
        test  al,1
        jne   in_retrace }
in_display:asm    {   
        in    al,dx
        test  al,1                    // wait for hbl (horizontal return)
        je    in_display }            // new line
 
set_color: asm {               
        xor   dx,dx
        mov   ax,cx
        shl   ax,PRECIS
        mov   bx,count
        div   bx
        mov   bx,ax                   // BX = percent
 
        xor   al,al                   // set color 0 (background)
        mov   dx,0x3c8
        out   dx,al   
        inc   dx                      // mov        dx,0x3c9 optimisation
 
        xor   ax,ax
        mov   al,step_red             // get RED level
        mul   bl
        shr   ax,PRECIS               // reduce precision
        add   al,st_red
        out   dx,al                   // set RED to dac
 
        xor   ax,ax       
        mov   al,step_green           // get GREEN level
        mul   bl
        shr   ax,PRECIS
        add   al,st_green
        out   dx,al                   // set GREEN to dac
 
        xor   ax,ax       
        mov   al,step_blue            // get BLUE level
        mul   bl
        shr   ax,PRECIS
        add   al,st_blue
        out   dx,al                   // set BLUE to dac
        jmp   start }                 // get next operand                
 
clean_eocl: asm {
        xor   bl,bl                   // clear error operand       
        }               
eocl:asm {                 
        xor        al,al              // normally we should restore whole DAC's status 
        mov        dx,0x3c8           // but we only reset color 0 to black
        out        dx,al                 
        inc        dx
        out        dx,al              // turn to RGB 0,0,0
        out        dx,al
        out        dx,al
        sti               
 
        mov   copper_error, bl }      // set error (if any)       
}
 
void main()
{
    unsigned char running=1;
 
    textmode(3);
    clrscr();
 
    while (running)
    {
        running=(copper_error?0:1);
        if (kbhit())
        {
            running=0;
        }
        // do some stuffs
 
        printf("T h i s  I s  T h e  T e s t");
        DrawRaster(0x00, 0x00, 0x00,0xFF, 0x1F, 0xF0,200);
    }
}

To be continued…

back2root/tutoriaux/vga-avance-dac-part-1.1619985186.txt.gz · Dernière modification : 2021/05/02 21:53 de frater