; ------------------------------------------------------------------------------------------------
; Play a tune when a key is pressed, stop playing when the key is released
; Exit when ESC is pressed. Port 61h is used by the sound card.
;
; ------------------------------------------------------------------------------------------------
IDEAL
MODEL small
STACK 100h
DATASEG
CODESEG
proc Play	
; play a tune
	push ax             ;preserve ax just in case you use it elsewhere.
	in 	al, 61h         ;activate the speaker by reading from port 61h, 
	or 	al, 00000011b   ;turning on the two rightmost bits & writing it back.
	out 61h, al
	

	
	
	mov al, 0b6h         ;ports 43h and 42h are used for the sound. 43h gets 0b6h    
	out 43h, al       
	
	;port 42h gets a value which is a 'divisor' of: 1193180 to produce a certain sound.
	;For example: If we want the sound of 'La' in the first octave, it is 440hz, so the
	;divisor will be: 2712  ( 1193180 / 2712 is about 440). So 2712 in hexa is: 0A98h.
	;port 42h is only 8 bits, so we first pass the low order (98h) and then the high (0Ah)	
    ;We can only use ax or al for moving values to 42h.	 A note higher would be 440 times
    ;12th root of 2 (about 1.059), hence: 461, and the divisor would be 2559 (09ffh)  

    mov ax, 98h  ;0FFh  ; for a note higher
	out 42h, ax
	mov ax, 0ah  ;09h   ; for a note higher
	out 42h, ax
	pop ax
	ret
endp Play

proc Stop	
; stop playing
	push ax
	in 	al, 61h         ;Turning off the speaker by turning off
	and al, 11111100b   ;the rightmost two bits. 
	out 61h, al
	pop ax
	ret
endp Stop

start:
	mov ax, @data
	mov ds, ax
	; check initial scan code
	in 	al, 60h		
	mov dl, al
wait4event:		
	; look for a change in the scan code (any key we hit changes the scan code)
	in 	al, 60h          ; al gets the scan code
	cmp al, dl           ; no change -> continue to wait (idle loop) 
	je 	wait4event
	; exit when ESC pressed
	cmp	al, 1            ; 1 is the scan code of pressing Esc. 
	je exit
	; check if the change was press or release of key
	mov dl, al
	and al, 80h		     ; if the result is 0 a key is pressed
					     ; and if it is 1 a key is released
	jnz	stopplay
startplay:
	; key down = play a tune		
	call Play		
	jmp wait4event       ;Now wait for the event of releasing the key.	
stopplay:		
	; key up = stop playing
	call Stop		
	jmp wait4event       ;after we released, we can press again, so wait again.
exit:
	mov ax, 4c00h
	int 21h
END start

