Technical Notes
OverviewOn 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.
_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.
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.
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.