Miscellaneous Hardware

Reference Section

_get_timer0
_get_timer0mode
_get_timer2
_get_vec
_is_3270
_is_compaq
_reset_timer0
_set_timer0
_set_timer2
_set_vec
_sound_beep
_sound_change
_sound_off
_sound_on
_sound_pulse

_get_timer0


Descrip
Reads system timer zero.

Syntax
#include <mischard.h>
unsigned int _get_timer0(void);

Returns
The current count from system timer 0.

Notes
This function reads the current count from system timer zero without disrupting the counting process. The count is then returned. System timer zero is normally used to generate the BIOS time-of-day interrupt.

Hardware limitations make it difficult to determine the timer's current mode of operation and reload value. _get_timer0mode must be used for this purpose.

If this function is called with interrupts off, they will remain off during the entire duration of the function.

C/C++ Example
	{
	   int count = _get_timer0 ();
	   ...
	}

Inline Assembly Example
	#include <inline.h>
	   ...
	   get_timer0 ();	/* CX = count */
	   ...

Source file _MHGTMR0.ASM ASM equiv GET_TIMER0
See also
_get_time, get_timer2, _set_time

_get_timer0mode


Descrip
Determines the counting mode and reload value for system timer zero.

Syntax
#include <mischard.h>
int _get_timer0mode(unsigned int *reload);

Returns
The current mode of operation for timer 0.
reload reload value

Notes
This function returns the current programmed counting mode and reload value for system timer zero. The returned values for mode and reload are "educated guesses". They cannot be read directly from the timer because of hardware limitations.

System timer zero is used as the system clock timer and generally produces a BIOS time-of-day (INT 8) interrupt 18.2 times a second. Most BIOS power on self-test routines initialize this timer to mode three with a reload value of zero (so it counts 64k times before generating an interrupt). Some applications and TSRs reprogram the timer to mode two to facilitate high-resolution timing. This function makes it possible to estimate the programmed state of this timer after it has been reprogrammed.

This function assumes that mode is MODE_2 or MODE_3 and that binary counting (non-BCD) is being performed since other modes are less useful for generating time-of-day interrupts. MODE_3 is returned only if counter mode 3 is detected. Otherwise, MODE_2 is assumed and returned. (Note that MODE_2 = 0x04 and MODE_3 = 0x06. These values are used because they are the same values used to program the timer to operate in the corresponding modes. See _set_timer0.)

The following symbolic constants (defined in MISCHARD.H) represent the possible system timer mode values:

MODE_2 (0x04) Rate Generator
MODE_3 (0x06) Square Wave Rate Generator

This function also assumes that the current reload value is 65536/2n, where n is an integer in the range 0 ó n ó 15. Programming system timer zero with a reload value of 65536/2n increases the interrupt rate by a factor of 2n. This allows accurate system time to be maintained by passing control to the original interrupt handler every 2nth interrupt. Programming the reload value to any other number would make it very difficult to maintain the system time accurately. Reload values less than 210 or 1024 (64 times the default interrupt rate), may not be determined accurately on 4.77MHz PCs.

C/C++ Example
	{
	   unsigned int reload, mode;
	   ...
	   mode = _get_timer0mode (&reload);
	   ...
	}

Inline Assembly Example
	#include <inline.h>
	   get_timer0mode ();/* AL=mode, CX=reload value */

Source file _MHT0MOD.ASM ASM equiv GET_TIMER0MODE
See also
_get_time, _set_time

_get_timer2


Descrip
Reads system timer two.

Syntax
#include <mischard.h>
unsigned int _get_timer2(void);

Returns
The current count from system timer 2.

Notes
This function reads and returns the current count from system timer two without disrupting the counting process. System timer two is normally used to drive the system speaker.

Hardware limitations make it difficult to determine the timer's current mode of operation and reload value. See _get_timer0mode for an example of how this information is determined for system timer zero.

If this function is called with interrupts off, they will remain off during the entire duration of the function.

C/C++ Example
	{
	   int count;
	   ...
	   count = _get_timer2 ();
	   ...
	}

Inline Assembly Example
	#include <inline.h>

	   get_timer2 ();	/* CX=count */

Source file _MHGTMR2.ASM ASM equiv GET_TIMER0
See also
_get_time, _set_time

_get_vec


Descrip
Gets an interrupt handler address.

Syntax
#include <mischard.h>
void (interrupt far * _get_vec(int intnum))();

Returns
Interrupt handler address for intnum.

Notes
This function returns the address of the interrupt handler which is currently servicing intnum. The interrupt handler address is obtained by reading the system interrupt table directly.

This function is faster than _get_vect because it does not use DOS services. If this function is called with interrupts off, they will remain off during the entire duration of the function.

C/C++ Example
	{
	   void (interrupt far *intptr)();
	   ...
	   intptr = _get_vec(0x24);
	   ...
	}

Inline Assembly Example
	#include <inline.h>
	{
	   ...
	   mov bl,0x24	/* bl = int # */
	   get_vec ();/* DX:AX -> int routine for "int #" */
	   ...
	}

Source file _MHGVEC.ASM ASM equiv GET_VEC
See also
_get_vec, _set_vec

_is_3270


Descrip
Determines whether or not the host computer is an IBM 3270-PC.

Syntax
#include <mischard.h>
int _is_3270(void);

Returns
1 if the host computer is an IBM 3270-PC computer.

0 if the host computer is not an IBM 3270-PC computer.

Notes
This function checks the host computer to determine if it is an IBM 3270-PC computer.

3270-PC computers have a number of unique characteristics which require special programming attention. For example, the 3270 keyboard generates "make" codes for most key presses without generating associated "break" codes. Also, only 8 foreground colors are available in color text modes.

C/C++ Example
	   if (_is_3270 ())
	   {
	      ...
	   } else
	   {
	      ...
	   }

Inline Assembly Example
	#include <inline.h>
	   ...
	   is_3270 ();
	    je is_3270_010/* if the host computer is a 3270 */
	   ... 	 /* if the host computer is not a 3270 */
	   jmp short is_3270_020

	is_3270_010:
	   ... 	 /* handle special 3270 setup */
	is_3270_020:
	...
	}

Source file _MH3270.ASM ASM equiv IS_3270

_is_compaq


Descrip
Determines whether or not the host computer is a COMPAQ computer.

Syntax
#include <mischard.h>
int _is_compaq(void);

Returns
1 if the host computer is a COMPAQ computer.

0 if the host computer is not a COMPAQ computer.

Notes
This function checks the host computer to determine if it is a COMPAQ computer. The return value indicates the result of the test.

C/C++ Example
	   if (_is_compaq ())
	   {
	      ...
	   } else
	   {
	      ...
	   }

Inline Assembly Example
	#include <inline.h>
	   ...
	   is_compaq ();
	    je compaq_010/* if the host computer is COMPAQ */
	   ... 	 /* if the host computer is not COMPAQ */
	   jmp short compaq_020

	compaq_010:
	   ... 	 /* if the host computer is COMPAQ */
	compaq_020:
	   ...
	}

Source file _MHCMPAQ.ASM ASM equiv IS_COMPAQ

_reset_timer0


Descrip
Sets the counting mode and reload value for system timer zero to the system default values.

Syntax
#include <mischard.h>
void _reset_timer0(void);

Returns
None

Notes
This function forces timer zero into the system default counting mode.

The timer is programmed for mode three (square wave), non-BCD counting with a reload value of zero (counts 64k times before interrupting). This results in an interrupt rate of about 18.2 times per second. System timer zero is normally used to generate the BIOS time-of-day interrupt (INT 08h).

If this function is called with interrupts off, they will remain off during the entire duration of the function.

C/C++ Example
	   _reset_timer0 ()

Inline Assembly Example
	#include <inline.h>
	   reset_timer0 ();

Source file MHRTMR0.ASM ASM equiv RESET_TIMER0
See also
_get_time, _set_time

_set_timer0


Descrip
Sets the counting mode and reload value for system timer zero.

Syntax
#include <mischard.h>
void _set_timer0(int mode, unsigned int reload);

Returns
None

Notes
This function programs system timer zero to use counting mode mode with a reload value of reload. Timer zero is normally used to generate BIOS time-of-day interrupts (INT 8).

mode may be any one of the following:

MODE_0(0x00) Interrupt on Terminal Count
MODE_1(0x02) Retriggerable One-Shot
MODE_2(0x04) Rate Generator
MODE_3(0x06) Square Wave Rate Generator
MODE_4(0x08) Software Triggered Strobe
MODE_5(0x0A) Hardware Triggered Strobe
BCD_COUNT(0x01) Binary coded decimal (BCD) counting

The BCD_COUNT flag must be used in conjunction with one of the mode flags by bitwise ORing the two flags together. If BCD counting is specified, the timer counts in BCD mode and the maximum reload value is 9999. Otherwise, the timer counts in binary mode with a maximum count of 64K. (The maximum count is the system default and is specified using a reload value of 0). The symbolic constants listed above are defined in MISCHARD.H. For a more detailed explanation of the counting modes, refer to manufacturer specifications for the 8253/8254 timer/counter chip.

WARNING! No checking is done to ensure that mode is valid.

If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	{
	   int reload;
	   ...
	   _set_timer0 (MODE_0, reload);
	   ...
	}

Inline Assembly Example
	#include <inline.h>
	   {
	      int reload;
	      ...
	   	  mov al,MODE_0
	   	  mov cx,reload
	   	  set_timer0 ();/* set mode to "MODE_0" */
	   	  ... 	/*   and reload value "reload" */
	   }

Source file _MHSTMR0.ASM ASM equiv SET_TIMER0
See also
_get_time, _get_time, _set_time

_set_timer2


Descrip
Sets the counting mode and reload value for system timer two.

Syntax
#include <mischard.h>
void _set_timer2(int mode, unsigned int reload);

Returns
None

Notes
This function programs system timer two to use counting mode mode with a reload value of reload. Timer two is normally used to drive the system speaker.

mode may be any one of the following:

MODE_0(0x00) Interrupt on Terminal Count
MODE_1(0x02) Retriggerable One-Shot
MODE_2(0x04) Rate Generator
MODE_3(0x06) Square Wave Rate Generator
MODE_4(0x08) Software Triggered Strobe
MODE_5(0x0A) Hardware Triggered Strobe
BCD_COUNT(0x01) Binary coded decimal (BCD) counting

The BCD_COUNT flag must be used in conjunction with one of the mode flags by bitwise ORing the two flags together. If BCD counting is specified, the timer counts in BCD mode and the maximum reload value is 9999. Otherwise, the timer counts in binary mode with a maximum count of 64K. (The maximum count is specified using a reload value of 0). The symbolic constants listed above are defined in HARDWARE.H. For a more detailed explanation of counting modes, refer to manufacturer specifications for the 8253/8254 timer/counter chip.

WARNING! No checking is done to ensure that mode is valid. If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	{
	   int reload;
	   _set_timer2 (MODE_3, reload);
	   ...
	}

Inline Assembly Example
	#include <inline.h>
	{
	   int reload;
	   ...
	   mov al,MODE_3
	   mov cx,reload
	   set_timer2 ();/* set timer 2 to mode "MODE_3" */
	   ... 	 /*   and reload value "reload" */
	}

Source file _MHSTMR2.ASM ASM equiv SET_TIMER0
See also
_get_time, _set_time

_set_vec


Descrip
Sets an interrupt vector directly.

Syntax
#include <mischard.h>
void (interrupt far *_set_vec (int intnum, intaddr new_int))();

Returns
The previous interrupt handler address.

Notes
This function sets the address of the interrupt handler for intnum to new_int. The address of the replaced interrupt vector is returned. The interrupt handler address is set by manipulating the system interrupt table directly. If this function is called with interrupts off, they remain off during the entire duration of the function.

Because this function returns the previous interrupt handler address, the interrupt vector can checked at the time it is being restored. For example, if the active interrupt vector is not the same as the originally installed handler, then another handler has been installed and restoration may not be possible. Immediately calling _set_vec a second time (with the return value from the first call) will abort the restoration process. Interrupts should remain off throughout this process.

See the _isr_... functions for flexible, high-level alternatives to the use of this function.

new_int should be cast as intaddr when calling this function. This prevents the compiler from generating assembly language SEG instructions, which preclude the use of .COM format in the TINY memory model. Some compilers also require type casting of interrupt functions in parameter lists to eliminate spurious compiler errors.

C/C++ Example
	void interrupt far func ()
	{
	   ...
	}
	{
	   void (interrupt far *old_int)();
	   ...
	   old_int = _set_vec (0x24, (intaddr) func);
	   ...
	   if ((intaddr) _get_vec (0x24) == (intaddr) func)
	   {
	      _set_vec (0x24, (intaddr) old_int);
	   } else
	   {
	      /* Handle the interrupt vector being changed */
	   }
	}

Inline Assembly Example
	#include <inline.h>
	   #ifdef __cplusplus
	      extern "C" void interrupt far func ()
	   #else
	      void interrupt far func ()
	   #endif

	   ...
	{
	   ...
	#if __TINY__
	   mov dx,cs
	#else
	   mov dx,seg func
	#endif
	   mov ax,offset func/* DX:AX -> new interrupt func */
	   mov bl,0x24	    /* bl = int # */
	   set_vec ();	/* DX:AX -> old interrupt func */
	   pushdx	 	/* preserve address of old 
	   	  	 	   interrupt routine */
	   pushax
	   ...
	   pop ax	 	/* restore address of old 
	   	  	 	   interrupt routine */
	   pop dx
	/* if current interrupt handler =! my interrupt handler, 
	   	  	 don't reinstall the old int handler */
	   cli 	 	/* turn interrupts off */
	   set_vec ();   	/* DX:AX -> previous int func */
	   cmp ax,offset func/* "previous" = "new" offset? */
	    jneset_vec_010/*   n: go abort restoration */
	#if __TINY__
	   mov cx,cs   	/*   y: "previous" seg = "new"? */
	   cmp dx,cx
	#else
	   cmp dx,seg func
	#endif
	    je set_vec_020/*     y: keep restoration */
	set_vec_010:
	   set_vec ();	/*     n: abort restoration */
	set_vec_020:
	   sti 	 	/* turn interrupts back on */
	   ...
	}

Source file _MHSVEC.ASM ASM equiv SET_VEC
See also
_get_vec, _isr_getstat, _isr_hremove, _isr_install, _isr_remove, _isr_remove, _set_vec

_sound_beep


Descrip
Generates a tone for a specified number of hundredths of a second.

Syntax
#include <mischard.h>
void _sound_beep(unsigned int freq, unsigned int time);

Returns
None

Notes
This function generates a tone at the frequency freq for time hundredths of a second. The duration of the tone is approximated using the system timer, which updates the system time approximately 18.2 times per second.

For more accurate tone durations, use _sound_pulse.

C/C++ Example
	   _sound_beep (10000, 50);

Inline Assembly Example
	#include <inline.h>
	   ...
	   mov ax,10000/* frequency = 10,000 Hz */
	   mov dx,50	/* duration = 0.5 sec. */
	   sound_beep ();	/* beep (0.5 sec at 10,000Hz) */
	   ...

Source file _MHSNDBP.ASM ASM equiv SOUND_BEEP
See also
_sound_on, _sound_pulse

_sound_change


Descrip
Changes the frequency of the current tone.

Syntax
#include <mischard.h>
void _sound_change(unsigned int freq);

Returns
None

Notes
This function changes the frequency of the current tone to freq without disturbing tone quality.

This function assumes that system counter two is in the correct mode. If it is not, the results are undefined.

System counter two is automatically set to the proper mode whenever _sound_on is called. However, _sound_on adversely affects tone quality if it is used to change the frequency while a tone is already being generated. _sound_change is provided to allow the tone to be changed without affecting tone quality. The normal programming sequence for tone generation is as follows:

Call _sound_on to initialize the speaker and generate the first tone.
Call _sound_change to change the tone. This may be repeated as often as required.
Call _sound_off to turn the sound generator off.

If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	{
	   /* produce a phaser sound */
	   int times, freq;
	   _sound_on (2500);
	   for (times = 6; times > 0; times--)
	   for (freq = 2500; freq > 0; freq--)
	   _sound_change (freq);
	   _sound_off ();
	}

Inline Assembly Example
	#include <inline.h>
	{  	  /* produce a phaser sound */
	   int times, freq;
	   ...
	   mov ax,2500	    /* AX = starting frequency */
	   sound_on ();
	   mov cx,6	/* CX = # of loops */
	sound_020:
	   sound_change ();/* change freq to value in AX */
	   dec ax	 	/* decrease freq, at 0 yet? */
	    jnzsound_020/*   n: loop again */
	   mov ax,2500	    /*   y: reset start frequency */
	    loopsound_020/* loop CX times */

	   sound_off ();
	   ...
	}

Source file _MHSNDCH.ASM ASM equiv SOUND_CHANGE
See also
_sound_on

_sound_off


Descrip
Turns off the system speaker.

Syntax
#include <mischard.h>
void _sound_off(void);

Returns
None

Notes
This function turns off the system speaker and sound generator.

If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	{
	   /* produce a phaser sound */
	   int times, freq;
	   _sound_on (2500);
	   for (times = 6; times > 0; times--)
	   for (freq = 2500; freq > 0; freq--)
	   _sound_change (freq);
	   _sound_off ();
	}

Inline Assembly Example
	#include <inline.h>
	{  /* produce a phaser sound */
	   int times, freq;
	...
	mov ax,2500	/* AX = starting frequency */
	sound_on ();
	mov cx,6	 /* CX = # of loops */
	sound_020:
	sound_change ();/* change freq to value in AX */
	dec ax 	 /* decrease freq, at 0 yet? */
	 jnzsound_020/*   n: loop again */
	mov ax,2500	/*   y: reset start frequency */
	 loopsound_020/* loop CX times */

	sound_off ();
	...
	}

Source file MHSNDOFF.ASM ASM equiv SOUND_OFF
See also
_sound_on

_sound_on


Descrip
Starts generating a tone on the system speaker.

Syntax
#include <mischard.h>
void _sound_on(unsigned int freq);

Returns
None

Notes
This function turns on the system speaker after programming the sound generator to emit a tone of frequency freq.

This function ensures that the sound generator is properly initialized by forcing timer two to count in mode three. This adversely affects tone quality if another tone is currently being generated. For this reason, _sound_change should be used whenever a new tone is required while another tone is being generated.

If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	{
	   /* produce a phaser sound */
	   int times, freq;
	   _sound_on (2500);
	   for (times = 6; times > 0; times--)
	   for (freq = 2500; freq > 0; freq--)
	   _sound_change (freq);
	   _sound_off ();
	}

Inline Assembly Example
	#include <inline.h>
	{  /* produce a phaser sound */
	   int times, freq;
	mov ax,2500	/* AX = starting frequency */
	sound_on ();
	mov cx,6	 /* CX = # of loops */
	sound_020:
	sound_change ();/* change freq to value in AX */
	dec ax 	 /* decrease freq, at 0 yet? */
	 jnzsound_020/*   n: loop again */
	mov ax,2500	/*   y: reset start frequency */
	 loopsound_020/* loop CX times */

	sound_off ();
	...
	}

Source file _MHSNDON.ASM ASM equiv SOUND_ON
See also
_sound_beep, _sound_change, _sound_off, _sound_pulse

_sound_pulse


Descrip
Generates a tone for a specified number of milliseconds.

Syntax
#include <mischard.h>
void _sound_pulse(unsigned int freq, unsigned int time);

Returns
None

Notes
This function generates a tone at the frequency freq for time milliseconds.

This function makes use of the millisecond timer sleep function (_sleep_msec). The duration of the tone is exact unless unusually long system interrupts occur.

The millisecond timer should be initialized prior to calling this function or the duration may be incorrect. _init_msec is provided for this purpose.

If this function is called with interrupts off, they remain off during the entire duration of the function.

C/C++ Example
	   _sound_pulse (10000, 500);

Inline Assembly Example
	#include <inline.h>
	   ...
	   mov ax,10000/* frequency = 10,000 Hz */
	   mov dx,500	/* duration = 0.5 sec. */
	sound_pulse ();	/* sound on for 0.5 sec 
		   	    at 10,000 Hz */
	...

Source file _MHSDPLS.ASM ASM equiv SOUND_PULSE
See also
_init_msec, _sound_beep, _sound_on