; sound.asm plays a note of an input frequency & duration on the speaker.
; Push the frequency in hertz, and then the duration in millisecs. onto the
; stack, and then call sound. It’s a near routine that fixes up the stack.
public sound
.model small
.data
nticks dd 0 ; number of ticks for delaying
.code
sound PROC near
; store the value ofthe note’s duration in millisecs in nticks
PUSH BP
MOV BP,SP
PUSHAD ; an instruction which pushes all the general and index
; registers onto the stack. POPAD, used below, pops them
; all in reverse order
mov bx,[bp+4] ; value of the duration into BX
movsx nticks, bx ; value of the duration intonticks
; program clock 0 to produce a 1000 hz signal
mov al,00110110b ; initialize timer 0
out 43h,al
mov ax,1193 ; latch to act as frequency divisor
out 40h,al ; send low byte of divisor
mov al,ah
out 40h,al ; send high byte of the divisor
; put the value of FREQ (sound frequency for the note) into DI
mov di,[bp+6] ; value of frequency into DI
; program clock 2 to produce the sound
mov al,10110110b ; initialize clock 2
out 43h,al ;
; evaluate the divisor required as timer_input-frequency/FREQ
mov dx,12h ; store 12 34DCh (1,193,180) into
mov ax,34dch ; DX:AX for DIV command (dividend)
div di ; obtain frequency divisor in AX
out 42h,al ; send low byte of divisor
mov al,ah
out 42h,al ; send high byte of divisor
; turn the sound on
in al,61h ; read PPI port
or al,00000011b ; set bits 0 and 1 of the port to 1
out 61h,al ; turn speaker and timer 2 clock on
; get current number of ticks since midnight
mov ax,0 ; Set ES to 40h
mov es,ax
; calculate the count of ticks to be reached before switching the sound off
mov edx,es:46Ch ; put current no. of ticks since into DX
; add the duration required
add edx, nticks
; wait for the evaluated no. of ticks in edx to be reached to provide
; the required duration for the note
Delay: cmp es:[6Ch],edx ; Has this no. of ticks been reached?
jb Delay ; if not, continue to wait
; turn the sound off
in al,61h ; read PPI port
and al, not 00000011b ; set bits 0 and 1 of port 61h to 1
out 61h,al ; turn speaker and timer 2 clock off
; restore the original frequency of timer 0 to 18.2 cyles per sec.
mov al,00110110b ; initialize timer 0 again
out 43h,al ; preparing to send new freq. divisor
mov al,0FFh ; low byte of divisor value 65535
out 40h,al ; send the low byte
out 40h,al ; send the high byte
popad ; see description of pushad above
pop bp
ret 4 ; this subroutine “fixes up” the stack
sound endp
end