* cormen book
[mascara-docs.git] / i86 / mtx-16-bit / mtx / samples / SERIAL / vid.c
blob3f9678f76cf5e1271d8ad4fd88bd841398dca9b4
1 /********************* Main Source of Infomation ************************
2 www.osdever.net/FreeVGA : home of FreeVGA programming information
3 www.osdever.net/FreeVGA/vga/crtcreg.htm : CRT Controller Registers
5 Index 00h -- Horizontal Total Register
6 Index 01h -- End Horizontal Display Register
7 Index 02h -- Start Horizontal Blanking Register
8 Index 03h -- End Horizontal Blanking Register
9 Index 04h -- Start Horizontal Retrace Register
10 Index 05h -- End Horizontal Retrace Register
11 Index 06h -- Vertical Total Register
12 Index 07h -- Overflow Register
13 Index 08h -- Preset Row Scan Register
14 Index 09h -- Maximum Scan Line Register
15 Index 0Ah -- Cursor Start Register
16 Index 0Bh -- Cursor End Register
17 Index 0Ch -- Start Address High Register
18 Index 0Dh -- Start Address Low Register
19 Index 0Eh -- Cursor Location High Register
20 Index 0Fh -- Cursor Location Low Register
21 Index 10h -- Vertical Retrace Start Register
22 Index 11h -- Vertical Retrace End Register
23 Index 12h -- Vertical Display End Register
24 Index 13h -- Offset Register
25 Index 14h -- Underline Location Register
26 Index 15h -- Start Vertical Blanking Register
27 Index 16h -- End Vertical Blanking
28 Index 17h -- CRTC Mode Control Register
29 Index 18h -- Line Compare Register
30 Among these, only Registers
31 10-11 control CURSOR height (# of scand lines)
32 12-13 display origin address
33 14-15 CURSOR position
34 are of interests here:
35 **************************************************************************/
36 /************************************************************************
37 HOW does PC's color display work:
38 0. Before vid_init(), MUST set to mono mode, otherwise, no display at all.
40 1, Screen = 25 rows X 80 cols = 4000 WORDs = [attribue byte|char byte]
41 8000 bytes
42 2. Video RAM at 0xB800, size=16 to 64 KB >> screen=8000 bytes;
43 To display a screen: write 8000 bytes (4000 WORDs) to the video RAM
44 at the ORG location; tell the display register where the ORG is.
45 The display hardware will display the 4000 chars from ORG to the screen.
47 3. Cursor shape and position can be changed by writing to CRT register
49 4. Software must keep track of the Cursor position (row,col). For each
50 char displayed, it must advance the Curcor by one word, which may change
51 (row,col): When col % 80 which may inc row
52 When row>= 25, must scroll up one row
54 5. To Scroll up one row:
55 inc org by one row (tell Hardware to display from the new org position)
56 write a row of blanks to ORG + one screen in video RAM
57 if the last row exceeds VRAM size, must physically copy CURRENT screen
58 to VRAM beginning and reset org to 0
59 *****************************************************************/
60 #define C_6845 0x3D0 /* port for 6845 color board */
62 #define VINDEX 4 /* 6845's index register */
63 #define VDATA 5 /* 6845's data register */
64 #define CUR_SIZE 10 /* 6845's cursor size register */
65 #define VID_ORG 12 /* 6845's origin register */
66 #define CURSOR 14 /* 6845's cursor position register */
68 #define LINE_WIDTH 80 /* # characters on a line */
69 #define SCR_LINES 25 /* # lines on the screen */
70 #define SCR_BYTES 8000 /* bytes of ONE screen=25*80 */
72 #define CURSOR_SHAPE 15 /* block cursor for MDA/HGC/CGA/EGA/VGA... */
74 // attribute byte: 0x0HRGB, H=highLight; RGB determine color
75 #define HGREEN 0x0A
76 #define HCYAN 0x0B
77 #define HRED 0x0C
78 #define HPURPLE 0x0D
79 #define HYELLOW 0x0E
81 ushort base = 0xB800; // VRAM base address
82 ushort vid_mask = 0x3FFF; // mask=Video RAM size - 1
83 int vid_port = C_6845; // vid port address
85 ushort offset; // current display position
86 int color; // atttirbute byte
87 int org; // current display origin
88 int row, column; // logical row, col position
90 // vid_init() initializes the display org=0 (row,col)=(0,0)
91 int vid_init()
93 int i, w;
94 org = row = column = 0;
95 color = HYELLOW;
97 set_6845(CUR_SIZE, CURSOR_SHAPE); // set cursor size
98 set_6845(VID_ORG, 0); // display origin to 0
99 set_6845(CURSOR, 0); // set cursor position to 0
101 //clear screen
102 w = 0x0700; // White, blank char // attribute byte=0000 0111=0000 0RGB
103 for (i=0; i<24*80; i++){
104 put_word(w, base, 0+2*i); // write 24*80 blanks to VGA memory
108 /*************************************************************************
109 scroll(): scroll UP one line
110 **************************************************************************/
111 int scroll()
113 int i;
114 ushort w, bytes;
116 // Normal scrolling using the 6845 registers.
118 // try offset = org + ONE screen + ONE more line
119 offset = org + SCR_BYTES + 2*LINE_WIDTH;
121 if (offset <= vid_mask){ // offset still within vram area
122 org += 2*LINE_WIDTH; // just advance org by ONE line
124 else{ // offset exceeds vram area ==> reset to vram beginning by
125 // copy current rows 1-24 to BASE, then reset org to 0
127 for (i=0; i<24*80; i++){
128 w = get_word(base, org+160+2*i);
129 put_word(w, base, 0+2*i);
131 org = 0;
134 // org has been set up correctly
135 offset = org + 2*24*80; // offset = beginning of row 24
137 // copy a line of BLANKs to row 24
139 w = 0x0C00; // HRGB=1100 ==> HighLight RED, Null char
141 for (i=0; i<80; i++)
142 put_word(w, base, offset + 2*i);
144 set_6845(VID_ORG, org >> 1); /// 6845 thinks in words
148 int putc(c) char c;
150 // display c to cursor position, advance cursor
152 int pos, w, offset;
154 if (c=='\n'){
155 row++;
156 if (row>=25){
157 row = 24;
158 scroll();
161 pos = 2*(row*80 + column);
162 offset = (org + pos) & vid_mask;
163 set_6845(CURSOR, offset >> 1);
164 return;
167 if (c=='\r'){
168 column=0;
170 pos = 2*(row*80 + column);
171 offset = (org + pos) & vid_mask;
172 set_6845(CURSOR, offset >> 1);
173 return;
176 if (c=='\b'){
177 if (column > 0){
178 column--;
180 pos = 2*(row*80 + column);
181 offset = (org + pos) & vid_mask;
182 put_word(0x0700, base, offset);
184 set_6845(CURSOR, offset >> 1);
186 return;
189 pos = 2*(row*80 + column);
190 offset = (org + pos) & vid_mask;
191 w = color;
192 w = (w << 8) + c;
194 put_word(w, base, offset);
196 column++;
198 if (column >= 80){
199 column = 0;
200 row++;
202 if (row>=25){
203 row = 24;
204 scroll();
208 pos = 2*(row*80 + column);
209 offset = (org + pos) & vid_mask;
210 set_6845(CURSOR, offset >> 1);
213 /*===========================================================================*
214 * set_6845 *
215 *===========================================================================*/
216 int set_6845(reg, val)
217 int reg; /* which register pair to set */
218 int val; /* 16-bit value to set it to */
220 /* Set a register pair inside the 6845.
221 * Registers 10-11 control the format of the cursor (how high it is, etc).
222 * Registers 12-13 tell the 6845 where in video ram to start (in WORDS)
223 * Registers 14-15 tell the 6845 where to put the cursor (in WORDS)
225 * Note that registers 12-15 work in words, i.e. 0x0000 is the top left
226 * character, but 0x0001 (not 0x0002) is the next character. This addressing
227 * is different from the way the 8088 addresses the video ram, where 0x0002
228 * is the address of the next character.
230 lock(); /* try to stop h/w loading in-between value */
231 out_byte(vid_port + VINDEX, reg); /* set the index register */
232 out_byte(vid_port + VDATA, (val>>8) & 0xFF); /* output high byte */
233 out_byte(vid_port + VINDEX, reg + 1); /* again */
234 out_byte(vid_port + VDATA, val&0xFF); /* output low byte */
235 unlock();
238 // change color syscall from Umode, just for fun
239 int chcolor(y) ushort y;
241 y &= 0x7F;
242 switch(y){
243 case 'r' : color=HRED; break;
244 case 'y' : color=HYELLOW; break;
245 case 'c' : color=HCYAN; break;
246 case 'g' : color=HGREEN; break;
250 int ktest()
252 int y,i,w,pos;
253 while(1){
254 printf("enter color [r|b|g|y|c|p] : ");
255 y = getc() & 0x7F;
256 switch(y){
257 case 'r' : color=HRED; break;
258 case 'y' : color=HYELLOW; break;
259 case 'c' : color=HCYAN; break;
260 case 'g' : color=HGREEN; break;
261 case 'p' : color=HPURPLE; break;
263 w = (color << 8) + y;
264 for (i=0; i<25*80; i++){
265 put_word(w, base, 0+2*i); // write 24*80 blanks to VGA memory
267 org = 0;
268 set_6845(VID_ORG, org >> 1); /// 6845 thinks in words
269 pos = 2*(25*80 + 80) + 2;
270 offset = (org + pos) & vid_mask;
272 row = 24; column=0;
273 set_6845(CURSOR, offset >> 1);
274 if (y=='q') break;