Newer
Older
Microsoft / screendoor / SOUND.ASM
@tundra tundra on 24 May 2012 2 KB Initial revision
		PAGE	40,132
		TITLE	IBM-PC Sound Generator
		SUBTTL	Copyright (c) 1986, 1987 T.A. Daneliuk
		NAME	SOUND
;
;
; SOUND.A - ROUTINE CALLABLE BY MICROSOFT C TO PRODUCE SOUND ON IBM-PC
;		LAST MODIFIED: 07/08 /87
;		COPYRIGHT (C) 1986, 1987 T.A. DANELIUK
;
;
; 	USAGE:	sound(FREQ,DURATION)
;	WHERE,	FREQ IS UNSIGNED IN HERTZ
;		DURATION IS UNSIGNED (18/SECOND)
;

INCLUDE		MSCMODEL.INC			; Model Equates

PORTB_8255	EQU	61H			; 8255 PORT B
FREQ_8253	EQU	42H			; 8253 TIMER LATCH
COMMAND_8253	EQU	43H			; 8253 TIME COMMAND REGISTER
CLOCKH		EQU	0012H			; CLOCK RATE HIGH BYTE - 1193180 HZ
CLOCKL		EQU	34DCH			; CLOCK RATE LOW BYTE

		IF	FARCODE
		X	EQU	6		;OFFSET OF ARGUMENTS
		ELSE
		X	EQU	4		;OFFSET OF ARGUMENTS
		ENDIF
;
;
DURATION	EQU	[BP+X+8]		; PARAMETER OFFSETS
FREQ		EQU	[BP+X+6]
ELAPSED		EQU	[BP+6]			; ELAPSED TIME TICKS STORED HERE
STARTL		EQU	[BP+4]			; STORES INITIAL TIMER COUNT
STARTH		EQU	[BP+2]
;
;
_TEXT		SEGMENT	BYTE PUBLIC 'CODE'
		ASSUME	CS:_TEXT

		PUBLIC	_sound
		IF	FARCODE
_sound		PROC	FAR
		ELSE
_sound		PROC	NEAR
		ENDIF
;
;
		XOR		AX,AX		; ZERO REGISTER
		PUSH		AX		; INIT. ELAPSED TIME
		PUSH		AX		; INIT. STARTL
		PUSH		AX		; INIT. STARTH
		PUSH		BP		; PRESERVE REGISTER
		MOV		BP,SP		; LOCAL STACK FRAME
		MOV		AX,FREQ		; MAKE SURE FREQ. <> 0!
		AND		AX,AX
		JZ		SOUND_DONE	; IF SO, SKIP THE WHOLE THING
		IN		AL,PORTB_8255	; GET CURRENT 8255 VALUE
		OR		AL,3		; TURN ON SPEAKER/GATE SIGNAL
		OUT		PORTB_8255,AL	; WRITE BACK TO 8255
		MOV		AL,0B6H		; TELL TIMER, FREQUENCY IS SENT NEXT 
		OUT		COMMAND_8253,AL
		MOV		DX,CLOCKH	; DIVIDE CLOCK RATE BY PASSED
		MOV		AX,CLOCKL	; FREQUENCY TO GET TOTAL
		MOV		CX,FREQ		; NUMBER OF TICKS TO WAIT
		DIV		CX
		OUT		FREQ_8253,AL	; LOW BYTE TO TIMER
		XCHG		AL,AH		; INTEL'S NEAT INSTRUCTION SET!
		OUT		FREQ_8253,AL	; HIGH BYTE TO TIMER
		XOR		AX,AX		; GET CURRENT TIMER COUNT IN CX:DX
		INT		1AH
		MOV		STARTH,CX	; SAVE FOR FUTURE REFERENCE
		MOV		STARTL,DX
DELAY:		MOV		AX,DURATION	; WAIT TILL ELAPSED TIME IS
		CMP		AX,ELAPSED	; >= DURATION PASSED ON STACK
		JBE		SOUND_OFF
		XOR		AX,AX		; GET CURRENT TIMER COUNT
		INT		1AH
		MOV		AX,STARTH	; GET STARTING TIME
		MOV		BX,STARTL
		SUB		DX,BX		; LOW WORD FIRST
		SBB		CX,AX		; HIGH WORD WITH CARRY
		JNZ		SOUND_OFF	; ONLY CAN DEAL WITH 16 BIT INTERVALS
		MOV		ELAPSED,DX	; SAVE TIME ELAPSED
		JMP		DELAY
SOUND_OFF:	IN		AL,PORTB_8255	; TURN OFF SPEAKER/GATE SIGNAL
		AND		AL,11111100B
		OUT		PORTB_8255,AL
SOUND_DONE:	POP		BP		; RESTORE ENVIRONMENT
		POP		AX		; BALANCE THE STACK
		POP		AX
		POP		AX
		RET				; THERE'S NO PLACE LIKE HOME!
;
;
_sound		ENDP
_TEXT		ENDS
		END