Miscellaneous Hardware

Technical Notes

Overview
Manipulating the System Timers
Generating Sound
Determining Machine Characteristics
Manipulating Interrupt Vectors Directly

Overview

This unit consists of functions which manipulate and return information about the system hardware. Functions are provided to read and write system timer zero (time-of-day) and system timer two (speaker), generate tones on the system speaker, and determine machine characteristics. Functions are also provided which manipulate system interrupt vectors directly.

Manipulating the System Timers

_set_timer2
Sets the counting mode and reload value for system timer two.
_get_timer2
Reads system timer two.
_set_timer0
Sets the counting mode and reload value for system timer zero.
_get_timer0
Reads system timer zero.
_get_timer0mode
Determines the counting mode and reload value for system timer zero.
_reset_timer0
Sets the counting mode and reload value for system timer zero to the system default values.
These functions manipulate the 8253/8254 timer/counter chip which is present in all IBM-compatible systems. The 8253/8254 contains three timers. One of six different counting modes can be selected for each timer. Regardless of the mode, counting can be performed in either binary or BCD. The current count may be read at any time from any timer. See a specification sheet for the 8253/8254 for detailed information about counting modes and programming considerations.

On IBM PC-compatible systems, timer zero is used as the system clock and timer two is used to drive the system speaker. Both may be safely reprogrammed as long as the BIOS time-of-day interrupt handler (INT 8) still receives control at the expected rate. Timer one, on the other hand, is used to control memory refresh and must not be reprogrammed.

System timer zero generates the BIOS time-of-day interrupt (INT 8) roughly 18.2 times a second. This timer is programmed by the BIOS POST to operate in mode three, non-BCD counting, with a reload value of zero (65536). Some applications reprogram this timer to mode two to simplify the timing of short intervals. Applications may also increase the interrupt rate to obtain greater timing resolution. In this case, the time-of-day interrupt is only passed on to the BIOS at the standard rate of 18.2 times per second; the other time-of-day interrupts are not passed on by the application.

System timer two serves as the sound generator. It is usually programmed to operate in mode three (square wave mode). The reload value is selected to generate the square wave output at a particular frequency. Since the output is tied directly to the system speaker, this generates a tone whenever the speaker is enabled.

The _get_timer0 and _get_timer2 functions return the current count of their respective timers without disrupting the counting process. _set_timer0 and _set_timer2 reprogram the counting modeand reload values for their respective timers. _reset_timer0 forces timer zero to the BIOS default state (mode three, non-BCD and reload value of zero).

Unfortunately, hardware limitations make it impossible to read a timer's operating mode and reload value directly. _get_timer0mode is provided as a solution to this problem; it can be used to determine the mode and reload value for timer zero. This function reads the timer many times and makes a highly-reliable estimate for the mode and reload values. The mode is assumed to be either mode two or mode three with binary (non-BCD) counting enabled. The reload value is assumed to be a number 65536/2n where 0 ó n ó 15 (65536, or 65536/20, is the same as zero since the reload value is an int). These assumptions are reasonably safe since any other mode of operation does not generate the required interrupts, and any reload value other than a power of two is difficult to use and still maintain clock interrupts 18.2 times a second.

Symbolic constants for each of the counting modes are defined in HARDWARE.H.

Generating Sound

_sound_on
Starts generating a tone on the system speaker.
_sound_change
Changes the frequency of the current tone.
_sound_off
Turns off the system speaker.
_sound_pulse
Generates a tone for a specified number of milliseconds.
_sound_beep
Generates a tone for a specified number of hundredths of a second.
These functions control the system sound generation hardware. They operate on system timer two and I/O port 0x61.

_sound_on forces system timer two into mode three (square wave) with a reload value that produces the desired frequency. It also gates the timer and speaker on. _sound_off gates the timer and speaker off. _sound_change assumes the timer is already in mode three and that the timer and speaker are gated on. This function simply changes the reload value to a value that results in the desired frequency. This eliminates the clicking sound caused by reprogramming the timer when the sound generator is already producing a tone.

_sound_pulse generates a tone for a specified number of milliseconds, and _sound_beep generates a tone for a specified number of hundredths of a second. _sound_pulse utilizes a millisecond timer to generate highly accurate durations whether or not interrupts are enabled. _sound_beep, on the other hand, uses the system timer, so the duration of the tone is only accurate to the nearest 1/18th of a second. _sound_beep also requires that interrupts be enabled when it is called. Note that _init_msec should be called to properly initialize the millisecond timer before _sound_pulse is used.

Determining Machine Characteristics

_is_compaq
Determines whether or not the host computer is a COMPAQ computer.
_is_3270
Determines whether or not the host computer is an IBM 3270-PC.
These functions determine some characteristics of the system hardware.

The _is_compaq function indicates whether or not the host computer is a Compaq computer. Most older Compaq computers with CGA (but not EGA) adapters have dual-mode or gray-scale monitors. This function can be used in conjunction with the _get_monitor function to anticipate the presence of a dual-mode display. Color text display attributes may then be adjusted as needed (i.e., by calling _set_attrtbl).

The _is_3270 function determines whether or not the host computer is an IBM 3270 PC. 3270 PC's behave much like IBM PC's, but they present a host of compatibility problems for the programmer.

Manipulating Interrupt Vectors Directly

_get_vec
Gets an interrupt vector directly from the interrupt table.
_set_vec
Sets an interrupt vector directly.
These functions directly manipulate system interrupt vectors. Unlike their counterparts in the miscellaneous DOS unit, these functions make it possible to set several interdependent interrupt vectors while leaving interrupts off. They are also much faster than their DOS counterparts.

Zortech C compilers do not support interrupt functions. To avoid error messages, the _get_vec and _set_vec functions are not defined when using this compiler. See the MISCHARD.H header file for more details.

Some programs which monitor the interrupt vector table may miss accesses to the vector table made with these functions.