;EXTONE.ASM	(version 1.0)	8/12/83
;A Utility for the Osborne Executive I		George Peace
;						Midlothian, Virginia
;						CompuServe 71555,1501
;Demonstration of the NOISE subroutine for controlling the speaker
;on the Executive I
;An interesting side-effect of this program is that occasionally the
;drive the program was loaded from remains selected. bug/missed interrupt?

	org	100h
	lxi	sp,stack
	jmp	start

tlow	equ	5		;duration for low tones
tmed	equ	25		;duration for medium tones
thigh	equ	125		;duration for high tones

timer:	dw	0000h
temp:	db	1

start:
	lxi	h,0		;initialize tone control to zero
	shld	timer		;and plant seed for the loop

loop1:
	lhld	timer		;retrieve last tone control value
	inx	h		;increment tone control value
	shld	timer		;save for next loop

;limit the demonstration to 200h different tones
	mov	a,h		;get high order byte of counter
	cpi	02h		;have 200h repeats yet?
	jz	done		;yes - all done

;shorten the tone duration when the lower tones begin
	mvi	b,tlow		;set tone duration for lows
	mov	a,h		;get high order byte of tone value
	cpi	01h		;have 100h repeats yet?
	jz	loop2		;leave duration at default for lows
	mov	a,l		;get low order byte of tone value
	mvi	b,thigh		;set long duration for highs
	cpi	80h		;have 0080h repeats yet?
	jc	loop2		;not yet - no change
	mvi	b,tmed		;set shorter tone duration for mediums
loop2:
	lhld	timer		;get tone control value
	call	noise		;make noise (HL=tone,B=duration)
	jmp	loop1		;...then change the tone a bit

done:
	jmp	0		;do warm boot

;--- beginning of NOISE subroutine ----------------------------------
;Subroutine to make noise on the Osborne Executive I (George Peace 8/12/83)
;This subroutine allows "standardized" control of the speaker from within
;a program.
; input: HL = tone control value (use low numbers produce high tones)
;	  B = tone duration
;  exit: all registers/flags unchanged
;note that both input parameters must be non-zero (at least 1) to operate
noise:
	push	psw		;save environment
	push	b
	shld	noisav		;save tone control value
	mov	a,b		;get tone duration
	ora	a		;if zero, 
	jz	noise2		;... exit as if never called
	mov	a,h		;get tone control
	ora	l		;if zero,
	jz	noise2		;... exit as if never called
noise1:
	lhld	noisav		;retrieve tone control value
	in	02h		;get original port control value
	sta	temp
	ori	00001000b	;set speaker bit on
	out	02h
	call	noisew		;measure length of time to leave noise on
	lda	temp		;get original port control byte
	out	02h		;and restore to its original state
	lhld	noisav		;restore tone control value
	call	noisew		;leave noise off same length as on
	dcr	b		;decrement tone duration counter
	jnz	noise1		;loop until done
noise2:	
	lhld	noisav		;restore environment
	pop	b
	pop	psw
	ret
noisew:
	mov	a,h		;count
	ora	l		; down
	dcx	h		;  to
	jnz	noisew		;   zero
	ret
noisav:	ds	2		;save area for caller's HL
;--- end of NOISE subroutine ----------------------------------------

	ds	20h
stack:	ds	2
	end
