Presentation on theme: "The CRTC Interface Essential aspects of display page and cursor control for standard 80-column by 25-row text."— Presentation transcript:
The CRTC Interface Essential aspects of display page and cursor control for standard 80-column by 25-row text
Motivation When a UNIX application wishes to write a text message to the display, and then wait for a keyboard-response from the user, the application will want a ‘cursor’ to be visible at the position where the next keystroke is going to be echoed EXAMPLE: Please type a number: We expect a blinking cursor to appear here
But it’s tedious to program… To write code that draws a blinking cursor on the screen would be a time-consuming chore for both programmer and processor: –You have to repeatedly ‘draw’ and then ‘hide’ –You have to setup careful timing controls –Your program-loop will keep the CPU busy! Fortunately the video system’s hardware is able to handle this tedious chore for you!
Info the CRTC engine needs The display hardware already knows how to do the timing for normal cursor blinking (i.e., usually about two blinks per second) Software only needs to tell the hardware a few specific pieces of information: –Where does the cursor appear (row, column)? –How large is the cursor? Where does it start and end within the 8x16 character-cell? –Which region of display-memory is visible?
Hardware registers The CRT Controller is a peripheral chip It implements 25 standard CRTC registers Access to these registers is accomplished via a multiplexing scheme which uses just two I/O port-addresses for color text: address-port:0x03D4 data-port:0x03D5
How it works The multiplexing scheme for access to the CRTC registers was designed to function as a two-step operation: –First, specify which register is to be accessed (by writing the register’s index to port 0x3D4) –Then, read (or write) to the specified register (by inputting, or outputting, at port 0x3D5) But a multi-step scheme is problematic for preemptive multitasking (also it is slow!)
A useful optimization To improve the multiplexing scheme when writing values to CRTC registers, the CPU is able to perform the two steps in a single ‘atomic’ fetch-execute cycle: Here the ‘outw’ instruction will write AL to port $0x03D4 and AH to port $0x03D5 mov$0x03D4, %dx mov$0xFF14, %ax outw%ax, %dx
Cursor-related CRTC registers For text-mode cursor-control, we are concerned with just 6 (of the 25) standard CRTC registers: Index 0x0A:CURSOR_START Index 0x0B:CURSOR_END Index 0x0C:START_ADDRESS_HI Index 0x0D:START_ADDRESS_LO Index 0x0E:CURSOR_LOCATION_HI Index 0x0F:CURSOR_LOCATION_LO
CURSOR START/END dis- able starting_scanline skewending_scanline 76543210 76543210 Index 0x0A: Index 0x0B: CURSOR_START REGISTER CURSOR_END REGISTER NOTE: The ‘skew’ capability works by delaying the cursor’s appearance for 0, 1, 2, or 3 character-cells (i.e., shifting the cursor toward the right). When Is this useful? We couldn’t find any examples. Recommend skew be zero.
Changing the visual page 7654321076543210 START_ADDRESS_HISTART_ADDRESS_LO register-index 0x0C register-index 0x0D Programming example: # switches display to vram page 5 # the word-offset for page 5 is 0x2800 (= 5 * 2048) mov$0x03D4, %dx# port-address in register DX mov$0x280C, %ax# value=0x28, register=0x0C out%ax, %dx# write value to CRTC register mov$0x000D, %ax# value=0x00, register=0x0D out%ax, %dx# write value to CRTC register
Moving the CRT’s cursor 7654321076543210 CURSOR_LOCATION_HICURSOR_LOCATION_LO register-index 0x0Eregister-index 0x0F Programming example: // moves cursor to row 5, column 9, on page 0 mov$0x03D4, %dx// port-address in register DX mov$5, %bx// row-number imul$80, %bx// times cells-per-row add$9, %bx// plus column-number mov%bh, %ah// cursor offset’s MSB mov$0x0E, %al// CURSOR_HI index out%ax, %dx// write value to CRTC register mov%bl, %ah// cursor offset’s LSB mov$0x0F, %al// CURSOR_LO index out%ax, %dx// write value to CRTC register
Scrolling the screen Here’s a code-fragment that will scroll the contents of vram page 0 up by one line: mov$0xB800, %ax// address vram page 0 mov%ax, %ds// with DS register mov%ax, %es// also ES register mov$0, %di// destination is the top line mov$160, %si// source is one line lower cld// do forward copying mov$3840, %cx// 24 times 160 repmovsb// perform the copying mov$0x0720, %ax// blank character w/color mov $80, %cx// characters on bottom line repstosw// fill final line with blanks
Linux uses hardware scrolling The value of the CRT START_ADDRESS is reprogrammed, to change the region of visible vram by one line (i.e., add #80) So instead of subdividing vram into eight 4KB pages, the entire 32KB vram is one continuous page, but only partially visible To scroll up by one line, Linux adds $80 to the value of the CRT_START_ADDRESS
The ROM-BIOS variables Several variables in the ROM-BIOS DATA AREA are used by the VIDEO ROM-BIOS routines (i.e., int-0x10) to keep track of the current visisible page and of the positions of the cursors on each of the eight pages The locations of these variables are part of the IBM-PC BIOS standard, and as such they are widely documented
Standard data-addresses 0x449 (byte) current video mode-number 0x44A (word) number of columns on screen 0x44C (word) current page-size (in bytes) 0x44E (word) current page-address 0x450 (byte array) cursor-positions (col,row) 0x460 byte-pair) cursor type (END, START) 0x462 (byte) current display page-number 0x463 (word) CRTC base i/o port-address
Real-mode INT-0x10 services Function 0x00: set_display_mode Function 0x01: set_cursor_type Function 0x02: set_cursor_position Function 0x03: get_cursor_position_and_type Function 0x05: select_new_video_page Function 0x06: scroll_current_page_up Function 0x07: scroll_current_page_down Function 0x08: read_char_and_attrib_from_screen Function 0x09: write_char_and_attrib_to_screen Function 0x0A: write char_only_to_screen Function 0x0E: write_teletype_to_active_page Function 0x0F: return_video_status Function 0x13: write_string NOTE: These ROM-BIOS services are not available in protected-mode
Cursor-movement demo To illustrate reprogramming of the six CRT controller registers, we wrote ‘arrows.s’ It lets the user control the cursor position and visible page by using arrow-keys It also changes the height of the cursor An unusual feature (not recommended) is its use of “polled mode” keyboard device- programming (instead of “interrupt-driven”)
Polling the status-register The keyboard controller’s interrupt is masked The keyboard controller’s status-register is read and reread in a tight loop until bit #0 gets set, indicating that a key was pressed (or released) and hence the output-buffer register is now “full” So then the output-buffer register is read by the CPU to get the key’s “scancode” For the arrow-keys, the cursor will get moved Other keys are just ignored (except ESCAPE)
Disadvantage of polling Almost all of the CPU’s time is consumed by continually reading the status-register So this would not be a good design to use in writing a multitasking operating system! On the other hand, for single-tasking it has the advantage of not requiring an Interrupt Service Routine to be written, so the demo code we write can be shorter and simpler
Another noteworthy feature The ‘arrows.s’ demo uses a ‘jump-table’ to efficiently dispatch control to appropriate subroutines, based on a variable’s value This is a similar programming situation to using a ‘switch’ statement in C/C++ The jump-table avoids the long chain of ‘compare-and-branch’ statements for all the various possible cases that can occur
In-Class exercise To insure your mastery of the jump-table concept, and cement your grasp of how the CRTC START_ADDRESS registers are programmed, try modifying the demo to incorporate these additional actions: when one of the function-keys F1-F7 is pressed, the display is switched to the correspondingly numbered display-page