Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование видеоадаптеров.

© Александр Фролов, Григорий Фролов
Том 21, М.: Диалог-МИФИ, 1993.

[Назад] [Содеожание] [Дальше]

Регистры цифро-аналогового преобразователя VGA

Видеоадаптеры VGA и SVGA предназначены для подключения к аналоговым мониторам, имеющим три раздельных видеовхода. Сигнал на каждом из них управляет, соответственно, интенсивностью красного, зеленого и синего цвета изображения. Аналоговое напряжение для монитора формируется из двоичной цветовой информации при помощи трех ЦАП.

Цветовая 8-битовая информация, поступающая от контроллера атрибутов (рис. 4.19), преобразуется согласно таблице цветов в три 6-битовые сигнала для трех ЦАП. Такая схема позволяет одновременно отображать на экране 256 различных цветов, каждый из которых можно отдельно выбрать из 26+6+6 = 218 = 262144 возможных цветов.

Рисунок 4.19 Схема управления цветами видеоадаптера VGA

Таблица цветов фактически является набором из 256 18-битовых регистров. Используя регистры ЦАП, можно получить доступ для чтения и для записи к каждому регистру таблицы цветов.

ЦАП видеоадаптера VGA управляется пятью регистрами, перечисленными в следующей таблице:

Адрес

Регистр

3C6h

Регистр маскирования пикселов (Pixel Mask Register - PMR)

3C7h

Регистр состояния ЦАП (для чтения) (DAC State Register - DAC_SR)

3C7h

Индекс читаемого регистра таблицы цветов (для записи) (Look-up Table Read Index Register - LTRIR)

3C8h

Индекс записываемого регистра таблицы цветов (Look-up Table Write Index Register - LTWIR)

3C9h

Регистр данных таблицы цветов (Look-up Table Data Register - LTDR)

Регистр маскирования пикселов
(Pixel Mask Register - PMR)

Фирма IBM в руководстве видеоадаптера VGA предупреждает, что доступ к регистру нежелателен. В противном случае могут разрушиться данные в таблице цветов.

Регистр состояния ЦАП
(DAC State Register - DAC_SR)

Регистр адресуется при помощи порта с адресом 3C7h и доступен только для чтения. Прочитав данные из регистра, можно определить, доступны регистры цветовой таблицы для чтения или же они доступны для записи.

D1-D0 Если биты D0 D1 содержат двоичное число 11b, то регистры цветовой таблицы доступны для записи, если D0 D1 содержат двоичное число 00b (шестнадцатиричное 0), то регистры цветовой таблицы доступны для чтения.

D7-D2 Не используются.

Индекс читаемого регистра таблицы цветов
(Look-up Table Read Index Register - LTRIR)

Этот индексный регистр доступен через порт 3C7h только для записи. Запись в данный регистр индекса элемента цветовой таблицы позволяет прочитать его через регистр данных цветовой таблицы.

D7-D0 Индекс регистра таблицы цветов (0-255).

Данные из регистров таблицы цветов читаются через порт 3C9h, как три 6-битовых числа. После чтения третьего числа значение индексного регистра (LTRIR) автоматически увеличивается на единицу, что позволяет прочитать всю таблицу цветов, загрузив регистр индекса только один раз.

Во время операций чтения или записи таблицы цветов прерывания должны быть запрещены.

Индекс записываемого регистра таблицы цветов
(Look-up Table Write Index Register - LTWIR)

После записи в регистр LTWIR индекса регистра таблицы цветов можно записать в него новое значение через регистр данных таблицы цветов (см. ниже).

D7-D0 Индекс регистра таблицы цветов (0-255).

Данные записываются в регистры таблицы цветов через порт 3C9h, как три 6-битовых числа. После записи третьего числа значение индексного регистра (LTWIR) автоматически увеличивается на единицу, что позволяет прочитать таблицу цветов, загрузив регистр индекса только один раз.

Регистр данных таблицы цветов
(Look-up Table Data Register - LTDR)

Регистр используется для получения доступа к регистрам таблицы цветов. Для чтения и записи одного элемента таблицы цветов необходимо три раза прочитать (записать) содержимое регистра данных. При этом каждый раз считывается (записывается) шесть очередных битов. Первые шесть битов отвечают за интенсивность красного, вторые - зеленого и третьи - синего цвета.

Нельзя прерывать цикл чтения регистров таблицы цветов, состоящий из трех операций чтения, выполнением операции записи в другой регистр таблицы и наоборот. Во время доступа к регистру LTDR прерывания должны быть запрещены. Между операциями доступа к регистрам таблицы цвета необходимо выдержать временной интервал не менее 240 наносекунд.

D5-D0 Данные для обмена с регистрами таблицы цветов.

D7-D6 Не используется.

Программа VGA256 (листинг 4.13) записывает новые значения в таблицу цветов непосредственно через регистры цифро-аналогового преобразователя VGA. На экране монитора отображается пять вертикальных полос различного цвета. Каждая полоса состоит из 64 вертикальных линий. Интенсивность цвета этих линий плавно уменьшается слева на право.

Листинг 4.13. Файл VGA256.C


#include	<stdio.h>
#include	<conio.h>
#include	"sysp.h"
#include	"sysgraph.h"
#include	<dos.h>

// Описания функций
int	main( void );
void	SetVideoMode( unsigned char );
void	Hello(void);

// Функция SetVgaDAC определена в файле DACTABLE.ASM
void __pascal __far	SetVgaDAC(unsigned, unsigned);

//===========================================================
// Главная функция
//===========================================================
int main( void )
{
	RGB	color_table[256];
	int	error, x_num, y_num;
	unsigned	i, j, iii;
	unsigned	seg_table,off_table;
	unsigned char	far *ptr;

// Записываем в массив color_table новые значения для
// регистров таблицы цветов
	for(j = 0; j < 4; j++) {
		for(i = 0; i < 64; i++) {
			(color_table[i+j*64]).red = 
				(j == 0) ? i : 0;
			(color_table[i+j*64]).green = 
				(j == 1) ? i : (j == 3) ? i : 0;
			(color_table[i+j*64]).blue = 
				(j == 2) ? i : (j == 3) ? i : 0;
		}
	}

// Устанавливаем режим видеоадаптера номер 13h (256 цветов)
// данный режим поддерживается только VGA и Super VGA
	SetVideoMode( 0x13 );

// Определяем сегмент и смешение массива color_table
	ptr = (unsigned char far*) &color_table[0];
	seg_table = FP_SEG(ptr);
	off_table = FP_OFF(ptr);

// Загружаем новые значения в регистры таблицы цветов
	SetVgaDAC(seg_table,off_table);

// Записываем в ptr указатель на начало видеопамяти
	ptr = (unsigned char far*) (FP_MAKE(0xA000, 0x0));

// Выводим на экран вертикальные линии различного цвета,
// процессор записывает данные непосредственно в видеопамять
	for(y_num = 0; y_num < 200; y_num++) {
		for(x_num = 0; x_num < 320; x_num++) {
			*ptr = (unsigned char) x_num;
			ptr++;
		}
	}

// Ожидаем нажатие на клавишу
	getch();

// Плавно гасим изображение на экране, уменьшая значения
// регистров таблицы цветов
	for(i=0;i<320;i++){
		for(iii=0;iii<256;iii++)  {

			(color_table[iii]).red =
				((color_table[iii]).red>6) ? 
				color_table[iii].red-1 : 1;

			(color_table[iii]).green =
				((color_table[iii]).green>6) ? 
				color_table[iii].green-1 : 1;

			(color_table[iii]).blue =
				((color_table[iii]).blue>6) ? 
				color_table[iii].blue-1 : 1;
		}
		SetVgaDAC(seg_table,off_table);
	}

// Ожидаем нажатие на клавишу
	SetVideoMode( 0x3 );
	Hello();

	return 0;
}


//===========================================================
// Функция SetVideoMode устанавливает режим работы 
// видеоадаптера, заданный параметром vmode
//===========================================================
void SetVideoMode( unsigned char vmode ) {

	union  REGS    inregs, outregs;

	inregs.h.ah = 0x0;
	inregs.h.al = vmode;
	int86( 0x10, &inregs, &outregs );
}


//===========================================================
// Функция Hello выводит на экран краткую справку о программе
//===========================================================
void Hello(void) {

	printf("\nCopyright (C)Frolov G.V.,1995. "
			 "E-mail: frolov@glas.apc.org\n");
}

Функция SetVgaDAC, предназначенная для заполнения таблицы цветов, представлена в листинге 4.14.

Листинг 4.14. Файл DACTABLE.ASM

TITLE DACTABLE.ASM NAME DACTABLE PAGE 55,132 P286 IDEAL NOWARN BRK SEGMENT VGA_TEXT WORD PUBLIC 'CODE' ASSUME cs:VGA_TEXT ;============================================================ ; Функция ; void SetVgaDAC(unsigned seg_table, unsigned off_table) ;============================================================ off_table EQU [bp+6] seg_table EQU [bp+8] PUBLIC SETVGADAC PROC SETVGADAC FAR enter 0, 0 ; Сохраняем регистры DS и ES push ds push es ; Устанавливаем регистр ES на начало оперативной памяти xor ax,ax mov es,ax ; Получаем адрес порта индексного регистра контроллера ЭЛТ ; (3B4h/3D4h), в монохромных режимах для адресации к ; индексному регистру используется порт с адресом 3B4h, а ; в цветных - порт 3D4h mov dx,es:[463h] ; Вычисляем адрес порта регистра состояния 1, в ; монохромных режимах для адресации к регистру состояния 1 ; используется порт с адресом 3BAh, а в цветных порт 3DAh add dx,6 pop es ; Ожидаем начало обратного вертикального хода луча in al,dx nop nop ; Если бит D3 равен единице, то происходит обратный ; вертикальный ход луча test al,08h jz wait_on wait_off: in al,dx nop nop test al,08h jnz wait_off wait_on: in al,dx nop nop test al,08h jz wait_on ; Устанавливаем индекс первого записываемого регистра ; таблицы цветов mov dx,3C8h ; Начинаем модифицировать таблицу цветов с первого ; регистра mov ax,1 out dx,al ; Задержка nop nop ; Устанавливаем DS:SI на массив данных, записываемых ; в регистры таблицы цветов mov ax,seg_table mov ds,ax mov si,off_table ; Загружаем 256 регистров (по 3 байта на регистр) mov cx,(256 * 3) ; Выбираем регистр данных таблицы цветов (порт 3C9h) mov dx,3C9h cld ; Загружаем все регистры таблицы цветов get_reg: lodsb out dx,al nop nop loop get_reg ; Восстанавливаем регистр DS pop ds leave ret 4 ENDP SETVGADAC ENDS VGA_TEXT END
[Назад] [Содеожание] [Дальше]